数据绑定 WPF 中 WebBrowser 的 Source 属性
Posted
技术标签:
【中文标题】数据绑定 WPF 中 WebBrowser 的 Source 属性【英文标题】:databind the Source property of the WebBrowser in WPF 【发布时间】:2010-09-20 18:48:38 【问题描述】:有谁知道如何在 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>
【问题讨论】:
您也可以使用特殊的separate proxy control。它不仅适用于 WebBrowser 案例,还适用于任何此类控件。 【参考方案1】:问题是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"/>
【讨论】:
在“new Uri(uri)”上获取异常,因为字符串是“”。也许应该是.... browser.Source = string.IsNullOrEmpty(uri) ? null : 新的 Uri(uri); 请注意,这只是单向绑定,当浏览器页面改变时,BindableSource 属性不会改变。 作为一个新手,这对我来说有点难以理解——写一些关于在绑定的 ViewModel 中为“WebAddress”设置一个私有-公共 getter setter 并为 Property changed 更新事件会有所帮助。这个项目有一个类似的例子。 github.com/thoemmi/WebBrowserHelper 谢谢。我接受并修改它以实现一个“html”属性,该属性在后台调用 NavigateToString。 @pgee70 谢谢,我按照你的 github 示例进行了操作【参考方案2】:这是对 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 中的项目不为空时,然后在分配时,如果新值是 URI,则使用它。如果不是并且 URI 为空,那么它必须是一个可以放入 URI 的字符串;因为 #1 强制字符串不能为空。
【讨论】:
【参考方案3】:你需要在指向类文件的xaml
文件的前几行声明它
xmlns:reportViewer="clr-namespace:CoMS.Modules.Report"
【讨论】:
【参考方案4】:我稍微修改了 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;
【讨论】:
【参考方案5】:托德好主意。
我现在对 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"/>
【讨论】:
【参考方案6】:我写了一个包装用户控件,它利用了 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,并且总是会覆盖其他元素(例如:在滚动查看器中这可能会导致一些麻烦) 有关这些 win32-wpf 问题的更多信息,请访问MSDN
【讨论】:
这正是我想要显示自己的 html 所需要的。整洁,简单,我几乎明白它在做什么(-:以上是关于数据绑定 WPF 中 WebBrowser 的 Source 属性的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 wpf WebBrowser 控件之上呈现 WPF 控件?
StackPanel中的WebBrowser不会在WPF中扩展到其内容大小