WPF: Document binding with WebBrowser control

The WebBrowser control in WPF is an excellent control for embedding a web browser in your WPF application. If you want to show a HTML document in your WPF app this control is also the way to go. However, in this current version of the control (up until WPF 4) it is not possible to use databinding because there is no dependency property available that you can use. The only possibility is invoking the method NavigateToString(string) somewhere in code.

Although this is working it doesn’t fit nicely in the currently popular MVVM pattern, in which everything (at least as much as possible) should be done using databinding. Moreover, when you want to display a browser control in every item of a listbox, a databinding solution is much simpler.

One of the solutions to solve this problem is to create a new custom control that derives from the WebBrowser control and adds a new dependency property to which you can databind your document. When the property changes you can simply invoke NavigateToString(string).

Another solution is using WPF’s ‘Attached Properties’ which can be used to extend existing controls with new properties and/or behaviors. In the code below I’ve created a new dependency property called Document. When this property changes the event handler DocumentPropertyChanged is executed that invokes the method NavigateToString(string) of the WebBrowser. This causes to control to display the document.

public static class WebBrowserExtentions
{
  public static readonly DependencyProperty DocumentProperty =
      DependencyProperty.RegisterAttached("Document", typeof(string), typeof(WebBrowserExtentions), new UIPropertyMetadata(null, DocumentPropertyChanged));

  public static string GetDocument(DependencyObject element)
  {
    return (string)element.GetValue(DocumentProperty);
  }

   public static void SetDocument(DependencyObject element, string value)
   {
     element.SetValue(DocumentProperty, value);
   }

   public static void DocumentPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
   {
     WebBrowser browser = target as WebBrowser;
     if (browser != null)
     {
       string document = e.NewValue as string;
       browser.NavigateToString(document);
     }
   }
}

To use this new property in XAML you can simply do the following:

<WebBrowser local:WebBrowserExtentions.Document="{Binding HtmlDoc}" />

The WebBrowser is now bound to the property HtmlDoc of the provided DataContext (which will probably be a ViewModel in case of MVVM).

Question is though, is this better than creating a new control that is derived from WebBrowser? Personally I don’t think there is a real winner, but I do like the power of attached properties. One scenario that requires attached properties are controls that are sealed and thus inheritance is not possible.