在WPF中对WebBrowser的Source属性进行数据绑定


85

有谁知道如何在WPF(3.5SP1)中对WebBrowser的.Source属性进行数据绑定?我有一个列表视图,我想在左侧有一个小的WebBrowser,在右侧是内容,并希望将每个WebBrowser的源与绑定到列表项的每个对象中的URI进行数据绑定。

到目前为止,这就是我作为概念证明所得到的,但是“ <WebBrowser Source="{Binding Path=WebAddress}"”没有编译。

<DataTemplate x:Key="dealerLocatorLayout" DataType="DealerLocatorAddress">                
    <StackPanel Orientation="Horizontal">
         <!--Web Control Here-->
        <WebBrowser Source="{Binding Path=WebAddress}"
            ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
            ScrollViewer.VerticalScrollBarVisibility="Disabled" 
            Width="300"
            Height="200"
            />
        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal">
                <Label Content="{Binding Path=CompanyName}" FontWeight="Bold" Foreground="Blue" />
                <TextBox Text="{Binding Path=DisplayName}" FontWeight="Bold" />
            </StackPanel>
            <TextBox Text="{Binding Path=Street[0]}" />
            <TextBox Text="{Binding Path=Street[1]}" />
            <TextBox Text="{Binding Path=PhoneNumber}"/>
            <TextBox Text="{Binding Path=FaxNumber}"/>
            <TextBox Text="{Binding Path=Email}"/>
            <TextBox Text="{Binding Path=WebAddress}"/>
        </StackPanel>
    </StackPanel>
</DataTemplate>

Answers:


157

问题是那WebBrowser.Source不是一个DependencyProperty。一种解决方法是使用某种AttachedProperty魔术来启用此功能。

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;
        }
    }

}

然后在您的xaml中执行以下操作:

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

9
由于字符串为“”,因此在该“新Uri(uri)”上获取异常。也许应该是...。browser.Source = string.IsNullOrEmpty(uri)吗?null:新的Uri(uri);
2011年

5
请注意,这只是一种绑定方式,当Web浏览器页面更改时,BindableSource属性不会更改。
Kurren 2015年

1
作为一个新手,这对我来说有点困难-写一些关于在绑定的ViewModel中为“ WebAddress”使用私有-公共getter设置方法,并更改Property更新事件会有所帮助。这个项目有一个类似的例子。github.com/thoemmi/WebBrowserHelper
pgee70

谢谢。我对此进行了修改,以实现“ Html”属性,该属性在后台调用NavigateToString。
安东尼·斯科特

@ pgee70谢谢,我遵循了您的github示例并进行了请客
percentum

33

我对Todd的出色答案做了一些修改,以产生一个可以处理来自Binding来源的字符串或Uris的版本:

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;
    }

31

我编写了一个包装器用户控件,该控件使用了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);
    }
}

并像这样使用它:

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

唯一的麻烦是WebBrowser控件不是“纯”的wpf ...它实际上只是Win32组件的包装器。这意味着控件将不遵守z-index,并且将始终覆盖其他元素(例如:在scrollviewer中,这可能会引起一些麻烦)有关MSDN上这些win32-wpf问题的更多信息


这正是我想要显示自己的html所需要的。整洁,简单,我几乎明白它在做什么(-:
Murph

3

好主意托德。

我现在在Silverlight 4中对RichTextBox.Selection.Text做过类似的操作。感谢您的帖子。工作正常。

public class RichTextBoxHelper
{
    public static readonly DependencyProperty BindableSelectionTextProperty =
       DependencyProperty.RegisterAttached("BindableSelectionText", typeof(string), 
       typeof(RichTextBoxHelper), new PropertyMetadata(null, BindableSelectionTextPropertyChanged));

    public static string GetBindableSelectionText(DependencyObject obj)
    {
        return (string)obj.GetValue(BindableSelectionTextProperty);
    }

    public static void SetBindableSelectionText(DependencyObject obj, string value)
    {
        obj.SetValue(BindableSelectionTextProperty, value);
    }

    public static void BindableSelectionTextPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        RichTextBox rtb = o as RichTextBox;
        if (rtb != null)
        {
            string text = e.NewValue as string;
            if (text != null)
                rtb.Selection.Text = text;
        }
    }
}    

这是Xaml代码。

<RichTextBox IsReadOnly='False' TextWrapping='Wrap' utilities:RichTextBoxHelper.BindableSelectionText="{Binding Content}"/>


0

这是对Todd和Samuel的答案的改进,以利用一些基本的逻辑前提以及使用空合并运算符。

public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    WebBrowser browser = o as WebBrowser;

    if ((browser != null) && (e.NewValue != null))
        browser.Source = e.NewValue as Uri ?? new Uri((string)e.NewValue);

}
  1. 如果浏览器为null或位置为null,我们将无法使用或导航至null页面。
  2. 如果#1中的项目不为null,则在分配时,如果新值是URI,则使用它。如果不是,并且URI为null,则必须合并为可以放入URI的字符串。因为#1强制字符串不能为null。

-3

您需要在xaml指向类文件的文件 的前几行中声明它

xmlns:reportViewer="clr-namespace:CoMS.Modules.Report" 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.