2008-11-04 9 views
75

Qualcuno sa come associare la proprietà .Source del WebBrowser in WPF (3.5SP1)? Ho un listview che voglio avere un WebBrowser piccolo a sinistra, e il contenuto a destra, e per il database l'origine di ogni WebBrowser con l'URI in ogni oggetto associato alla voce di elenco.database della proprietà Source del WebBrowser in WPF

Questo è ciò che ho come prova del concetto fino ad ora, ma "<WebBrowser Source="{Binding Path=WebAddress}"" non viene compilato.

<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 * per correggere il tuo messaggio. – Donnelle

risposta

138

Il problema è che WebBrowser.Source non è una proprietà di dipendenza. Una soluzione alternativa sarebbe usare la magia AttachedProperty per abilitare questa abilità.

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

} 

Poi, nel tuo XAML fare:

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

Ottenere un'eccezione su quel "nuovo Uri (uri)" come la stringa è "". Forse dovrebbe essere ... browser.Source = string.IsNullOrEmpty (uri)? null: new Uri (uri); – midspace

+3

Si noti che questo è solo un collegamento unidirezionale e la proprietà BindableSource non cambierà quando la pagina del browser Web cambia. – Kurren

+0

Sei un risparmiatore di vita. Questo ha funzionato perfettamente. –

26

ho scritto un UserControl involucro, che si avvale delle 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); 
    } 
} 

e usarlo in questo modo:

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

L'unico problema con questo è che il controllo WebBrowser non è "pura" WPF ... in realtà è solo un wrapper per un componente win32. Ciò significa che il controllo non rispetterà il z-index, e sarà sempre sovrapporre altro elemento (ad esempio: in uno ScrollViewer questo potrebbe causare qualche problema) più informazioni su questi temi Win32 WPF su MSDN

+0

Questo è esattamente ciò di cui avevo bisogno poiché voglio visualizzare il mio html. Neat, semplice, e quasi capisco cosa sta facendo (-: – Murph

+0

Funziona come un campione, grazie! –

1

Si può anche utilizzare uno speciale separate proxy control. È applicabile non solo al caso WebBrowser, ma a qualsiasi controllo di questo tipo.

3

Cool idea Todd.

Ho eseguito la stessa operazione con RichTextBox.Selection.Text in Silverlight 4 ora. Grazie per il tuo post. Funziona bene.

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

Ecco il codice Xaml.

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

ho modificato eccellente risposta di Todd un po 'per la produzione di una versione che affronta sia con stringhe o Uris dalla sorgente Legatura:

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

È necessario dichiararla alle prime righe di il file xaml che punta al file di classe

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

Questo non fornisce molto supporto per risolvere il problema. – Woot4Moo

0

si tratta di un perfezionamento a Todd di e la risposta di Samuel per approfittare di alcune premesse logiche di base così come noi e l'operatore coalescente 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. Se il browser è nullo o la posizione è nullo, non possiamo usare o passare a una pagina nullo.
  2. Quando gli elementi in # 1 non sono nulli, quindi quando si assegna, se il nuovo valore è un URI, quindi utilizzarlo. In caso contrario e l'URI è nullo, la coalesce deve essere una stringa che può essere inserita in un URI; dal momento che # 1 impone che la stringa non può essere nulla.