导航时更改Web浏览器的附加属性

时间:2011-02-07 12:40:56

标签: c# wpf mvvm browser

我使用those文章来创建Webbrowser控件的AttachedProperty,因此我可以将“BindableSource”绑定到我的公共属性“Path”。这很好,并且有一个小缺点。 在我的ViewModel构造函数中,该属性设置为:

Path = new Uri("http://microsoft.com");

当页面加载时,我导航到另一个链接,“WebBrowser.Source”属性被更改,但“WebBrowser.BindableSource”未更改。 当我点击再次设置的按钮时:

 Path = new Uri("http://microsoft.com");

未调用“BindableSourcePropertyChanged”,因为该属性具有这些值。

我知道如何解决它,但它不好,因为性能降低,将Path设置为另一个URL,然后将其设置为真实URL(http://microsoft.com)。

   Path = new Uri("http://google.com");
   Path = new Uri("http://microsoft.com");

你能不能给我一个更好的主意,我怎么能解决它。 谢谢你提前。

1 个答案:

答案 0 :(得分:2)

我建议将BindableSource与Navigated事件同步。 您可以通过在WebBrowserUtility类中公开另一个附加行为来实现此目的,该行为会对Navigated事件做出如下反应:

    public static readonly DependencyProperty ShouldHandleNavigatedProperty =
        DependencyProperty.RegisterAttached(
            "ShouldHandleNavigated", 
            typeof(Boolean), 
            typeof(WebBrowserUtility), 
            new UIPropertyMetadata(false, ShouldHandleNavigatedPropertyChanged));

    public static Boolean GetShouldHandleNavigated(DependencyObject obj)
    {
        return (Boolean)obj.GetValue(BindableSourceProperty);
    }

    public static void SetShouldHandleNavigated(DependencyObject obj, Boolean value)
    {
        obj.SetValue(ShouldHandleNavigatedProperty, value);
    }

    public static void ShouldHandleNavigatedPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        WebBrowser browser = o as WebBrowser;
        if (browser != null)
        {
            if ((bool)e.NewValue)
            {
                browser.Navigated += new NavigatedEventHandler(Browser_Navigated);
            }
            else
            {
                browser.Navigated -= new NavigatedEventHandler(Browser_Navigated);
            }
        }
    }

    private static void Browser_Navigated(object sender, NavigationEventArgs e)
    {
        WebBrowser browser = sender as WebBrowser;
        if (browser != null)
        {
            browser.SetValue(WebBrowserUtility.BindableSourceProperty, browser.Source.AbsoluteUri);
        }
    }

xaml中的用法:

<WebBrowser self:WebBrowserUtility.BindableSource="{Binding WebAddress}"
            self:WebBrowserUtility.ShouldHandleNavigated="True"/>  

P.S。我应该承认这个实现相当脏,因为在Navigated事件处理程序中设置BindableSource会强制触发一个额外的事件。但是这段代码可行,您可以考虑一下它的改进。

<强> EDITED

    public static class WebBrowserUtility
    {
        ...
        private const string _SkipSourceChange = "Skip";

        public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            WebBrowser browser = o as WebBrowser;
            if (browser != null)
            {
                string uri = e.NewValue as string;
                if (!_SkipSourceChange.Equals(browser.Tag))
                {
                    browser.Source = uri != null ? new Uri(uri) : null;
                }
            }
        }

        private static void Browser_Navigated(object sender, NavigationEventArgs e)
        {
            WebBrowser browser = sender as WebBrowser;
            if (browser != null)
            {
                if (WebBrowserUtility.GetBindableSource(browser) != e.Uri.ToString())
                {
                        browser.Tag = _SkipSourceChange;
                        browser.SetValue(WebBrowserUtility.BindableSourceProperty, browser.Source.AbsoluteUri);
                        browser.Tag = null;
                }
            }
        }
    }