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.
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.
[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"> </pre>
</body>
</html>
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.