Navigating trough objects of a web page, using an

2019-06-03 09:07发布

问题:

I have a Windows Forms application that uses a WebBrowser control to display an embedded web page. The file is (successfully) loaded using:

webHelp.DocumentStream=
          Assembly.GetExecutingAssembly()
          .GetManifestResourceStream("MyAssembly.help.html");

In order for this to work (i.e. the file to be loaded/displayed) I set the webHelp.AllowNavigation = false;. I don't fully understand why, but if it's set to true, the page is not displayed.

In my HTML document (see bellow) I want to be able to navigate trough different sections. But when I click on a link, the browser control does not go to the targeted element. The web page works fine in the stand-alone Internet Explorer 10, so it must have something to do with the control, more specifically the AllowNavigation property. MSDN didn't help much.

How can I achieve this navigation behavior? Is there another way of loading the HTML file without setting the AllowNavigation property to false?

This is my simple HTML file:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Using this tool</title>
</head>
<body>
    <h3>Description</h3>
    <div><p id="contents">Contents</p></div>
    <div>
        <p id="general">Using the file converter</p>
        <p>*converter description*</p>
        <a href="#contents" class="goToTop">Go To Top!</a>
    </div>
    <div class="divBlock" >
        <p id="selectOption">Selecting a conversion action</p>
        <p>*action selection*</p>
        <a href="#contents" class="goToTop">Go To Top!</a>
    </div>
</body>
</html>

EDIT: After additional tests I found the root of the problem. The problem appeared after setting a value for the URL property, running the application and afterwards clearing this value. The embedded page is not loaded any more, unless the AllowNavigation property is set to false. There are two solutions, described in my answer bellow.

回答1:

I also have my own WebBrowser. I've tested it and it loads your HTML file perfectly. I simply used:

webBrowser1.Navigate("C:\\myPath\\SofNavigate.html");

When I click on links it goes to "#contents" without problems. I am not sure why you need to use webHelp.Docstream instead of simple Navigate. By the way, when I turn off navivation, then I am not able to go anywhere from the page that I started on. So Navigation must be on in order to go anywhere from the "home page".

Try to debug that part, as it appears to be the bigger problem that you have. Here is a good example on how to set up simple webBrowser. Try to use it as a base and see what you do differently that messes up your navigation.



回答2:

[EDITED] Win8/IE10, your code works for me unmodified inside Form.Load event on a simple form which has just a single WebBrowser control with all default settings (and WebBrowser.AllowNavigation is true by default). Check the properties of your WebBrowser control in the Designer, you may have something wrong in there.
[/EDITED]

You're using HTML5, which handles anchor links via id attribute (i.e. <p id="contents"> ... <a href="#contents">. By default, WebBrowser control works in legacy IE7 mode with HTML5 disabled. You need to turn it on with FEATURE_BROWSER_EMULATION feature control, before WebBrowser object gets created. The best place to do this is a static constructor of your form:

static MainForm()
{
    SetBrowserFeatureControl();
}

private static void SetBrowserFeatureControl()
{
    // http://msdn.microsoft.com/en-us/library/ee330730(v=vs.85).aspx#browser_emulation

    // FeatureControl settings are per-process
    var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);

    // make sure the control is not running inside Visual Studio Designer
    if (String.Compare(fileName, "devenv.exe", true) == 0 || String.Compare(fileName, "XDesProc.exe", true) == 0)
        return;

    // web pages containing standards-based !DOCTYPE directives are displayed in Standards mode
    using (var key = Registry.CurrentUser.CreateSubKey(
        @"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION",
        RegistryKeyPermissionCheck.ReadWriteSubTree))
    {
        key.SetValue(fileName, (UInt32)9000, RegistryValueKind.DWord);
    }
}

Try it and your links should work as expected. This solution does NOT require admin rights, the affected key is under HKEY_CURRENT_USER.

[UPDATE] There may be a better solution, it works at least for IE10 here on my side. Add <meta http-equiv="X-UA-Compatible" content="IE=edge" /> as below and leave the registry intact. If you see document.compatMode: CSS1Compat, document.documentMode: 10, you should be good to go, but test with older IE versions too.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title></title>
    <script type="text/javascript">
        window.onload = function () {
            info.firstChild.data = 
                "document.compatMode: " + document.compatMode +
                ", document.documentMode: " + document.documentMode;
        }
    </script>
</head>
<body>
    <pre id="info">&nbsp;</pre>
</body>
</html>


回答3:

EDIT: After finding the cause of the problem (see the edit to the question) I can now propose three solutions:

1. WebBrowser control replacement:
Simply delete the existing WebBrowser control and add a new one. This solution does not require any modification of the AllowNavigation property. DO NOT modify the URL property.

2. When deleting and adding a new WebBrowser control is not an option:
Since the AllowNavigation property was influencing the loading and displaying of the web page, there was no reason for it to be left to false afterwards. Setting back the property in the Shown event solved the navigation problem, without requiring other alterations (e.g. in the HTML file or the Registry):

private void helpForm_Shown(object sender, EventArgs e)
{
    webHelp.AllowNavigation = true;
}

3. Reseting the Document
It seams that the Document property gets (automatically) initialized if URL property is at one time set and reset. Adding webHelp.Document.OpenNew(true); before loading the resource stream solves the problem without the need for re-adding the WebBrowser and without modifying the AllowNavigation property.