databind thuộc tính Nguồn của WebBrowser trong WPF


85

Có ai biết cách lập dữ liệu thuộc tính .Source của WebBrowser trong WPF (3.5SP1) không? Tôi có một dạng xem danh sách mà tôi muốn có một WebBrowser nhỏ ở bên trái và nội dung ở bên phải và để lập dữ liệu nguồn của từng WebBrowser với URI trong mỗi đối tượng được liên kết với mục danh sách.

Đây là những gì tôi có như một bằng chứng về 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>

Câu trả lời:


157

Vấn đề là đó WebBrowser.Sourcekhông phải là a DependencyProperty. Một cách giải quyết là sử dụng một số AttachedPropertyphép thuật để 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 một Ngoại lệ trên "Uri mới (uri)" như chuỗi là "". Có lẽ nó phải là .... browser.Source = string.IsNullOrEmpty (uri)? null: new Uri (uri);
midspace

5
Lưu ý rằng đây chỉ là 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

1
là một người mới, điều này hơi khó đối với tôi - viết một cái gì đó về việc có bộ cài đặt getter riêng-công khai cho "WebAddress" trong ViewModel bị ràng buộc với một sự kiện cập nhật cho Thuộc tính đã thay đổi sẽ hữu ích. dự án này có một ví dụ tương tự. github.com/thoemmi/WebBrowserHelper
pgee70

cảm ơn. Tôi đã lấy điều này và sửa đổi nó để triển khai thuộc tính "Html", thuộc tính này gọi NavigateToString dưới mui xe.
Antony Scott,

@ pgee70, cảm ơn, tôi đã làm theo ví dụ trên github của bạn và làm việc rất tốt
trămum

33

Tôi đã sửa đổi câu trả lời tuyệt vời của Todd một chút để tạo ra một phiên bản đối phó với chuỗi hoặc Uris 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;
    }

31

Tôi đã viết một điều khiển người dùng trình bao bọ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}"  />

Rắc rối duy nhất với cái này là điều khiển WebBrowser không phải là wpf "thuần túy" ... nó thực sự chỉ là một trình bao bọc 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 phủ lên phần tử khác (ví dụ: trong trình xem cuộn, điều này có thể gây ra một số rắc rối) thông tin thêm về các sự cố win32-wpf này trên MSDN


Đâ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. Gọn gàng, đơn giản, và tôi gần như hiểu những gì làm nó (-:
Murph

3

Ý tưởng tuyệt vời Todd.

Tôi đã làm tương tự với RichTextBox.Selection.Text trong Silverlight 4 ngay bây giờ. Cảm ơn cho bài viết 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}"/>


0

Đây là sự cải tiến cho câu trả lời của Todd và Samuel để tận dụng một số tiền đề logic cơ bản cũng như sử dụng toán tử kết hợp null ..

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 trống hoặc vị trí trống, chúng tôi không thể sử dụng hoặc điều hướng đến trang trống.
  2. Khi các mục ở # 1 không 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ì liên kết với nó phải là một chuỗi có thể được đưa vào một URI; vì # 1 thực thi rằng chuỗi không được rỗng.

-3

Bạn cần khai báo nó ở vài dòng đầu tiên của xamltệp đang trỏ đến tệp lớp

xmlns:reportViewer="clr-namespace:CoMS.Modules.Report" 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.