Кто-нибудь знает, как привязать свойство .Source WebBrowser в WPF (3.5SP1)? У меня есть представление списка, в котором я хочу иметь небольшой 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>





Проблема в том, что 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}"/>
Получение исключения для этого «нового Uri (uri)» в виде строки «». Возможно, это должно быть .... browser.Source = string.IsNullOrEmpty (uri)? null: новый Uri (uri);
Обратите внимание, что это только односторонняя привязка, и свойство BindableSource не изменится при изменении страницы веб-браузера.
как новичку мне было немного сложно уследить за этим - помогло бы написать что-нибудь о том, чтобы установить частный-общедоступный геттер для "WebAddress" в связанной ViewModel с событием обновления для свойства изменено. в этом проекте есть похожий пример. github.com/thoemmi/WebBrowserHelper
благодаря. Я взял это и изменил, чтобы реализовать свойство «Html», которое вызывает под капотом NavigateToString.
@ pgee70 спасибо, я последовал вашему примеру на github и отлично работает
Я написал оболочку usercontrol, которая использует 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. Аккуратно, просто, и я почти понимаю, что он делает (-:
Классная идея Тодда.
Я сделал то же самое с RichTextBox.Selection.Text в Silverlight 4. Спасибо за ваш пост. Работает отлично.
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}"/>
Я немного изменил отличный ответ Тодда, чтобы создать версию, которая справляется со строками или 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;
}
Вам нужно объявить его в первых нескольких строках файла xaml, который указывает на файл класса.
xmlns:reportViewer = "clr-namespace:CoMS.Modules.Report"
Это уточнение ответа Тодда и Самуэля, позволяющее воспользоваться некоторыми базовыми логическими предпосылками, а также использовать оператор объединения с нулевым значением.
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);
}
Вы также можете использовать специальный отдельный прокси-контроль. Это применимо не только к случаю WebBrowser, но и к любому подобному элементу управления.