2008-11-04 28 views
75

Có ai biết cách databind thuộc tính .Source của WebBrowser trong WPF (3.5SP1) không? Tôi có một listview rằng tôi muốn có một WebBrowser nhỏ bên trái, và nội dung bên phải, và để databind nguồn của mỗi WebBrowser với URI trong mỗi đối tượng liên kết với mục danh sách.databind thuộc tính Nguồn của WebBrowser trong WPF

Đây là những gì tôi có làm bằng chứng khái niệm cho đến nay, nhưng "<WebBrowser Source="{Binding Path=WebAddress}"" không biên dịch.

<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> 
+0

* nudge * để sửa bài đăng của bạn. – Donnelle

Trả lời

138

Vấn đề là WebBrowser.Source không phải là DependencyProperty. Một cách giải quyết khác là sử dụng một số phép thuật AttachedProperty để kích hoạt khả năng này.

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

} 

Sau đó, trong XAML của bạn làm:

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

Nhận ngoại lệ về "Uri mới" (uri) "" khi chuỗi là "". Có lẽ nó phải là .... browser.Source = string.IsNullOrEmpty (uri)? null: Uri mới (uri); – midspace

+3

Lưu ý rằng đây chỉ là một ràng buộc một chiều và thuộc tính BindableSource sẽ không thay đổi khi trang trình duyệt web thay đổi. – Kurren

+0

Bạn là người bảo vệ cuộc sống. Điều này làm việc hoàn hảo. –

26

Tôi đã viết một usercontrol wrapper, mà làm cho việc sử dụng 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); 
    } 
} 

và sử dụng nó như vậy:

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

Vấn đề duy nhất với một này là sự kiểm soát WebBrowser không phải là "tinh khiết" WPF ... nó thực sự chỉ là một wrapper cho một thành phần win32. Điều này có nghĩa là điều khiển sẽ không tôn trọng chỉ mục z và sẽ luôn che phủ phần tử khác (ví dụ: trong trình xem ảnh này có thể gây ra một số sự cố) thông tin khác về các vấn đề về win32-wpf này trên MSDN

+0

Đây chính xác là những gì tôi cần khi tôi muốn hiển thị html của riêng mình. Neat, đơn giản, và tôi gần như hiểu được những gì nó làm (-: – Murph

+0

Làm việc như một nhà vô địch, cảm ơn bạn! –

1

Bạn cũng có thể sử dụng một số đặc biệt separate proxy control. Nó không chỉ áp dụng cho trường hợp WebBrowser mà còn cho bất kỳ điều khiển nào như vậy.

3

Ý tưởng hay Todd.

Tôi đã thực hiện tương tự với RichTextBox.Selection.Text trong Silverlight 4 ngay bây giờ. Cảm ơn bài đăng của bạn. Hoạt động tốt.

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

Đây là mã Xaml.

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

Tôi đã sửa đổi câu trả lời xuất sắc của Todd một chút để tạo ra một phiên bản mà đối phó với một trong hai dây hoặc URI từ nguồn Binding:

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

Bạn cần phải khai báo nó ở vài dòng đầu tiên của các xaml tập tin mà được trỏ đến tập tin lớp

xmlns:reportViewer="clr-namespace:CoMS.Modules.Report" 
+2

Điều này không cung cấp nhiều hỗ trợ để giải quyết vấn đề. – Woot4Moo

0

Đây là một cải tiến đối với Todd và trả lời Samuel để tận dụng lợi thế của một số cơ sở logic cơ bản cũng như chúng tôi e toán tử kết hợp rỗng.

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. Nếu trình duyệt là null hoặc vị trí là null, chúng ta không thể sử dụng hoặc điều hướng đến một trang null.
  2. Khi các mục trong # 1 không phải là rỗng thì khi gán, nếu giá trị mới là URI thì hãy sử dụng nó. Nếu không và URI là null, thì kết hợp lại cho nó phải là một chuỗi có thể được đặt vào một URI; vì # 1 thực thi chuỗi không thể rỗng.
Các vấn đề liên quan