WPF'de WebBrowser'ın Source özelliğini veri bağlama


86

WPF'de (3.5SP1) WebBrowser'ın .Source özelliğinin nasıl veritabanına bağlanacağını bilen var mı? Solda küçük bir WebBrowser ve sağda içerik olmasını ve liste öğesine bağlı her nesnedeki URI ile her bir WebBrowser kaynağını veritabanına bağlamak istediğim bir liste görünümüm var.

Şimdiye kadar bir kavram kanıtı olarak sahip olduğum şey bu, ama " <WebBrowser Source="{Binding Path=WebAddress}"" derlenmiyor.

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

Yanıtlar:


158

Sorun şu ki WebBrowser.Source, a değil DependencyProperty. Çözümlerden biri AttachedProperty, bu yeteneği etkinleştirmek için biraz sihir kullanmak olabilir .

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

}

Sonra xaml'inizde şunları yapın:

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

9
Dizge "" olduğu için bu "yeni Uri (uri)" hakkında bir İstisna alma. Belki de şu olmalıdır .... browser.Source = string.IsNullOrEmpty (uri)? boş: yeni Uri (uri);
orta boşluk

5
Bunun yalnızca tek yönlü bir bağlama olduğunu ve Web tarayıcısı sayfası değiştiğinde BindableSource özelliğinin değişmeyeceğini unutmayın.
Kurren

1
Bir acemi olarak bunu takip etmek benim için biraz zordu - bağlı ViewModel'de "WebAddress" için bir özel-genel alıcı ayarlayıcıya sahip olmak ve değiştirilen Mülk için bir güncelleme olayı ile ilgili bir şeyler yazmak yardımcı olurdu. bu projenin de benzer bir örneği var. github.com/thoemmi/WebBrowserHelper
pgee70

Teşekkürler. Bunu aldım ve başlık altında NavigateToString'i çağıran bir "Html" özelliğini uygulamak için değiştirdim.
Antony Scott

@ pgee70 teşekkürler, github örneğinizi takip ettim ve bir muamele yaptım
yüzde

33

Todd'un mükemmel cevabını biraz değiştirerek Binding kaynağından dizeler veya Uris ile baş edebilecek bir sürüm oluşturdum:

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

DependencyProperties'i kullanan bir sarmalayıcı kullanıcı denetimi yazdım:

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

ve şu şekilde kullanın:

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

Bununla ilgili tek sorun, WebBrowser kontrolünün "saf" wpf olmamasıdır ... aslında sadece bir win32 bileşeni için bir sarmalayıcıdır. Bu win32-wpf sorunlar hakkında daha fazla bilgi: Kontrol z-index saygı olmayacak ve her zaman (bu bazı problemler neden olabilecek bir ScrollViewer örn) diğer eleman bindirmek edeceği Bu araçlar MSDN


Kendi html'mi görüntülemek istediğim için tam da ihtiyacım olan şey buydu. Düzgün, basit ve ne yaptığını neredeyse anlıyorum (-:
Murph

3

Harika fikir Todd.

Şimdi Silverlight 4'te RichTextBox.Selection.Text ile benzer yaptım. Gönderiniz için teşekkürler. İyi çalışıyor.

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

İşte Xaml-Kodu.

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


0

Bu, Todd ve Samuel'in bazı temel mantık öncüllerinden yararlanmanın yanı sıra sıfır birleştirme operatörünü kullanma yanıtına yapılan bir iyileştirmedir ..

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. Tarayıcı boşsa veya konum boşsa, boş bir sayfayı kullanamayız veya bu sayfaya gidemeyiz.
  2. # 1'deki öğeler boş olmadığında, atama sırasında, yeni değer bir URI ise, o zaman onu kullanın. Değilse ve URI boşsa, o zaman birleşmek için bir URI'ye konulabilen bir dizge olması gerekir; # 1 dizenin boş olamayacağını zorladığından.

-3

Bunu xaml, sınıf dosyasına işaret eden dosyanın ilk birkaç satırında bildirmeniz gerekir.

xmlns:reportViewer="clr-namespace:CoMS.Modules.Report" 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.