WPF에서 WebBrowser의 Source 속성을 데이터 바인딩합니다.


85

누구든지 WPF (3.5SP1)에서 WebBrowser의 .Source 속성을 데이터 바인딩하는 방법을 알고 있습니까? 왼쪽에는 작은 WebBrowser가 있고 오른쪽에는 콘텐츠가 있고 목록 항목에 바인딩 된 각 개체의 URI를 사용하여 각 WebBrowser의 소스를 데이터 바인딩하려는 목록보기가 있습니다.

이것이 지금까지 개념 증명으로 가지고있는 것이지만 " <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하지 않은 것입니다 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
문자열이 ""이므로 "new Uri (uri)"에 대한 예외가 발생합니다. 아마도 .... browser.Source = string.IsNullOrEmpty (uri)? null : 새로운 Uri (uri);
midspace

5
이것은 단방향 바인딩 일 뿐이며 BindableSource 속성은 웹 브라우저 페이지가 변경 될 때 변경되지 않습니다.
Kurren 2015 년

1
초보자로서 이것은 따라하기가 조금 어려웠습니다. Property 변경에 대한 업데이트 이벤트를 사용하여 바인딩 된 ViewModel에서 "WebAddress"에 대한 private-public getter setter를 갖는 것에 대해 작성하는 것이 도움이 될 것입니다. 이 프로젝트에는 비슷한 예가 있습니다. github.com/thoemmi/WebBrowserHelper
pgee70

감사. 나는 이것을 가져 와서 내부에서 NavigateToString을 호출하는 "Html"속성을 구현하도록 수정했다.
Antony Scott

@ pgee70 감사합니다. 저는 귀하의 github 예제를 따르고 치료를 수행합니다
percentum

33

나는 Todd의 훌륭한 대답을 약간 수정하여 Binding 소스의 문자열 또는 Uris를 처리하는 버전을 생성했습니다.

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를 사용하는 래퍼 usercontrol을 작성했습니다.

XAML :

<UserControl x:Class="HtmlBox">
    <WebBrowser x:Name="browser" />
</UserControl>

씨#:

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-index를 존중하지 않고 항상 다른 요소를 오버레이합니다 (예 : scrollviewer에서 문제가 발생할 수 있음) MSDN의 win32-wpf 문제에 대한 자세한 정보


이것은 내 자신의 HTML을 표시하고 싶기 때문에 정확히 필요한 것입니다. 깔끔하고 간단하며 그 작업이 무엇인지 거의 이해합니다 (-:
Murph

3

멋진 아이디어 토드.

이제 Silverlight 4의 RichTextBox.Selection.Text와 비슷한 작업을 수행했습니다. 게시물 주셔서 감사합니다. 잘 작동합니다.

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

이것은 일부 기본 논리 전제를 활용하고 null 병합 연산자를 사용하기 위해 Todd와 Samuel의 답변을 개선 한 것입니다.

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. 브라우저가 null이거나 위치가 null이면 null 페이지를 사용하거나 탐색 할 수 없습니다.
  2. # 1의 항목이 null이 아닌 경우 할당 할 때 새 값이 URI이면이를 사용합니다. 그렇지 않고 URI가 null 인 경우 결합은 URI에 넣을 수있는 문자열이어야합니다. # 1은 문자열이 null 일 수 없도록 강제하기 때문입니다.

-3

xaml클래스 파일을 가리키는 파일 의 처음 몇 줄에서 선언해야 합니다.

xmlns:reportViewer="clr-namespace:CoMS.Modules.Report" 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.