Binding WebBrowser content in WPF

,

When you’re using a WebBrowser control in your WPF application, you may have noticed that you can’t bind the control’s content. WebBrowser has no property to set its content but a method named NavigateToString. So when you’re following a strict MVVM approach you’re lost because you don’t want any code-behind for your views.

But then there are attached properties. As their name implies they allow you to attach new properties to existing dependency objects. In your XAML code you apply such a attached property to your element and can access it as any other property of the object.

Ok, first here’s the code of an attached property to set a WebBrowser’s content:

public class WebBrowserHelper {
    public static readonly DependencyProperty BodyProperty =
        DependencyProperty.RegisterAttached("Body", typeof (string), typeof(WebBrowserHelper), new PropertyMetadata(OnBodyChanged));

    public static string GetBody(DependencyObject dependencyObject) {
        return (string) dependencyObject.GetValue(BodyProperty);
    }

    public static void SetBody(DependencyObject dependencyObject, string body) {
        dependencyObject.SetValue(BodyProperty, body);
    }

    private static void OnBodyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var webBrowser = (WebBrowser) d;
        webBrowser.NavigateToString((string)e.NewValue);
    }
}

The static BodyProperty defines the type of the attached property: its name is Body, the type is string, and whenever it is changed the method OnBodyChanged should be called.

The accessors for a attached property must be conventionally named SetXxx and GetXxx. They are called whenever you set or get the property’s value.

Last but not least OnBodyChanged is called when the value of the property has changed. The first parameter is the object the property is attached to, so we can cast it to WebBrowser and call its NavigateToString method.

The actual usage of the new Body property is pretty simple:

<WebBrowser
    src:WebBrowserHelper.Body="{Binding MyHtml}"
    />

given that the ViewModel has a property named MyHtml providing the desired content for the control.

A complete sample application is available on GitHub.

Tags: ,

Updated:

Comments

Anonymous

Good article solved my problem of not having Source as a dependency property, used same to bind with Source
Thanks

Anonymous

Hi,
Its not working. I get the error at run time xaml markup threw an exception.

Please provide the appropriate solution.

Thanks

Anonymous

hey this looks just what I need does anyone have this solution for silverlight 5? Has anyone tried this for silverlight project?

thanks again, slguy

Nitish

There is an ‘AirSpace Problem associated with WebBrowser’. Can you please help me resolving the problem WPF 3.5.
Problem : Not able to show any other WPF Control on top of WebBrowser control.

Raphael Ulrich

When you want to show two WebBrowsers at the same time, it does not work, because the DependencyProperty is static and the value is shared with all the WebBrowsers using it.

Dwayne

I have tried this and see this site is fairly old. Rookie question. I used this class in a folder called “HelperClasses”. How do I write the xmnls to look for HelperClasses/WebBrowserHelper in my solution?

kirko77

I don’t get it… this example simply displays the link string instead of the actual webpage.
How do you load up the actual page? Thanks

Thomas Freudenberg

That’s the intention of this task: to bind the content of the WebBrowser control to a property. Just imagine you want to display some dynamic HTML created by your application at runtime.

kirko77

Got it, thanks! I already found a very similar example where it actually displays the webpage.
Thanks for clarifying!

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...