databind Вихідна властивість WebBrowser у WPF


85

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

Відповіді:


157

Проблема в тому, що WebBrowser.Sourceце не a 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);
midspace

5
Зауважте, що це лише в один бік прив’язки, і властивість BindableSource не зміниться, коли зміниться сторінка веб-браузера.
Куррен

1
як новачкові мені було трохи важко дотримуватися - писати щось про те, щоб приватно-загальнодоступний сеттер для "WebAddress" у прив'язаному ViewModel із подією оновлення для Property змінено, могло б допомогти. цей проект має подібний приклад. github.com/thoemmi/WebBrowserHelper
pgee70

Дякую. Я взяв це і змінив його, щоб реалізувати властивість "Html", яке викликає NavigateToString під капотом.
Антоні Скотт

@ pgee70 дякую, я наслідував ваш приклад github і
працюю

33

Я трохи доповнив чудову відповідь Тодда, щоб створити версію, яка справляється з рядками або Uris з джерела 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

Я написав оболонку 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-індекс і завжди буде накладати інший елемент (наприклад: у програмі прокрутки це може спричинити певні проблеми) більше інформації про ці проблеми win32-wpf на MSDN


Це саме те, що мені потрібно, оскільки я хочу відобразити свій власний html. Охайний, простий, і я майже розумію, що це робить (-:
Мерф

3

Класна ідея Тодд.

Я зробив подібне з 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-Code.

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


0

Це уточнення відповіді Тодда та Семюеля, щоб скористатися деякими основними логічними передумовами, а також використовувати нульовий оператор злиття.

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. Якщо браузер нульовий або місце розташування нульове, ми не можемо використовувати нульову сторінку або перейти до неї.
  2. Коли елементи в # 1 не мають нульового значення, тоді при призначенні, якщо новим значенням є URI, використовуйте його. Якщо ні, і URI є нульовим, тоді злиття для нього має бути рядком, який можна вставити в URI; оскільки №1 встановлює, що рядок не може бути нульовим.

-3

Вам потрібно оголосити це на перших кількох рядках xamlфайлу, який вказує на файл класу

xmlns:reportViewer="clr-namespace:CoMS.Modules.Report" 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.