databind the Source property of the WebBrowser in WPF databind the Source property of the WebBrowser in WPF wpf wpf

databind the Source property of the WebBrowser in WPF


The problem is that WebBrowser.Source is not a DependencyProperty. One workaround would be to use some AttachedProperty magic to enable this ability.

public static class WebBrowserUtility{    public static readonly DependencyProperty BindableSourceProperty =        DependencyProperty.RegisterAttached("BindableSource", typeof(string), typeof(WebBrowserUtility), new UIPropertyMetadata(null, BindableSourcePropertyChanged));    public static string GetBindableSource(DependencyObject obj)    {        return (string) obj.GetValue(BindableSourceProperty);    }    public static void SetBindableSource(DependencyObject obj, string value)    {        obj.SetValue(BindableSourceProperty, value);    }    public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)    {        WebBrowser browser = o as WebBrowser;        if (browser != null)        {            string uri = e.NewValue as string;            browser.Source = !String.IsNullOrEmpty(uri) ? new Uri(uri) : null;        }    }}

Then in your xaml do:

<WebBrowser ns:WebBrowserUtility.BindableSource="{Binding WebAddress}"/>


I've amended Todd's excellent answer a little to produce a version that copes with either strings or Uris from the Binding source:

public static class WebBrowserBehaviors{    public static readonly DependencyProperty BindableSourceProperty =        DependencyProperty.RegisterAttached("BindableSource", typeof(object), typeof(WebBrowserBehaviors), new UIPropertyMetadata(null, BindableSourcePropertyChanged));    public static object GetBindableSource(DependencyObject obj)    {        return (string)obj.GetValue(BindableSourceProperty);    }    public static void SetBindableSource(DependencyObject obj, object value)    {        obj.SetValue(BindableSourceProperty, value);    }    public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)    {        WebBrowser browser = o as WebBrowser;        if (browser == null) return;        Uri uri = null;        if (e.NewValue is string )        {            var uriString = e.NewValue as string;            uri = string.IsNullOrWhiteSpace(uriString) ? null : new Uri(uriString);        }        else if (e.NewValue is Uri)        {            uri = e.NewValue as Uri;        }        browser.Source = uri;    }


I wrote a wrapper usercontrol, which makes use of the DependencyProperties:

XAML:

<UserControl x:Class="HtmlBox">    <WebBrowser x:Name="browser" /></UserControl>

C#:

public static readonly DependencyProperty HtmlTextProperty = DependencyProperty.Register("HtmlText", typeof(string), typeof(HtmlBox));public string HtmlText {    get { return (string)GetValue(HtmlTextProperty); }    set { SetValue(HtmlTextProperty, value); }}protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {    base.OnPropertyChanged(e);    if (e.Property == HtmlTextProperty) {        DoBrowse();    }} private void DoBrowse() {    if (!string.IsNullOrEmpty(HtmlText)) {        browser.NavigateToString(HtmlText);    }}

and use it like so:

<Controls:HtmlBox HtmlText="{Binding MyHtml}"  />

The only trouble with this one is that the WebBrowser control is not "pure" wpf... it is actually just a wrapper for a win32 component. This means that the control won't respect the z-index, and will always overlay other element (eg: in a scrollviewer this might cause some trouble)more info about these win32-wpf issues on MSDN