I normally blog about performance or scalability related topics. But – as I’ve been struggling with the WebBrowser control for the last couple of hours to do what I thought should be a simple task – I though it’s worth sharing my findings with you on this “functional” topic.

Scenario: Using WebBrowser control to render custom HTML and react on link clicks

I am working on a new integration of dynaTrace with Visual Studio Team System where Team System fires an event when a user changes the selection in a certain list control. My Plugin provides a control that is hosted by VSTS in a Tab and this control hosts a WebBrowser control to display content depending on the list selection. So when the user selects a new list item I am updating the data that is shown in the WebBrowser control. The generated HTML to be displayed contains links that the user can click on. The links are not real links on a WebPage but actually open a Dialog or send requests via a WebService interface.

My list of requirements therefore were

  • Display HTML content based on selected list item
  • Handle Link Click on my own instead of WebBrowser control trying to follow the link

Following image shows the control in action – nicely hosted by VSTS in a separate Tab:

I quickly figured out to

Everything worked fine with my first generated HTML page. Trouble started when I tried to set a new value to DocumentText. Although setting a new HTML text – the control seemed to dismiss my change. It turned out that I had to set AllowNavigation to TRUE in order to set a new text. It seems that internally the browser control is browsing to a new HTML page which was prevented. AllowNavigation is of course not what I wanted as I wanted to prevent link clicks to be followed by the WebBrowser control. Changing the property to TRUE just for the task to change the DocumentText property didn’t do the trick either. Seems that – once you prevent navigation you cannot change DocumentText.

Solution

After lots of different attempts and lots of blogs that I browsed I came up with the ultimate solution. Using the Navigating and Navigated events I was able to prevent the WebBrowser control from navigating to links that have been clicked but allowing the control to browse to the new HTML that I set via DocumentText.

Here is my code:

private bool allowNavigate = false;
public WebResultForDynaTrace()
{
  InitializeComponent();
  webBrowser.Navigating += new WebBrowserNavigatingEventHandler(webBrowser_Navigating);
  webBrowser.Navigated += new WebBrowserNavigatedEventHandler(webBrowser_Navigated);
}
void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
  allowNavigate = false;
}
void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
  if (allowNavigate) return;
  e.Cancel = true;

  // check which link was clicked and do my own actions
  if(e.Url.ToString().StartsWith("myAction1"))
    doAction1();
}
public void SetNewHTMLContent(string htmlContent)
{
  allowNavigate = true;
  webBrowser.DocumentText = htmlContent;
}

Conclusion

The WebBrowser control offers a great way to integrate HTML in your Rich Client Application. There are many managed and also unmanaged COM interfaces that you can use to interact with the control. I just found that some property changes impact the controls behavior in a way that I didn’t expect. I hope this blog entry helps you to avoid those long hours that I spent to figure this out.