【问题标题】:Change AttachedProperty of WebBrowser when navigating导航时更改 Web 浏览器的附加属性
【发布时间】:2011-06-22 17:24:52
【问题描述】:

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

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

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

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

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

我有一个想法如何解决它,但它并不好,因为性能很慢,它是将路径设置为另一个 URL,然后将其设置为真实 URL (http://microsoft.com)。

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

你能给我一个更好的主意,我该如何解决它。 提前致谢。

【问题讨论】:

    标签: c# wpf mvvm browser


    【解决方案1】:

    我建议将 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"/>  
    

    附:我应该承认这个实现相当肮脏,因为在 Navigated 事件处理程序中设置 BindableSource 会强制触发一个额外的事件。但是此代码有效,您可以考虑对其进行改进。

    已编辑

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

    【讨论】:

    • 感谢 Mate,您的解决方案没有错误并且有效,但无法解决我的问题,因为在某些页面上我使用了 POST 请求。它两次导航到同一页面,因此当导航完成时 BindableSourcePropperty 被更改并且 webbrowser 导航到同一页面。如果我使用 Post 请求,我会遇到麻烦。但谢谢,在某些情况下它可能很有用。
    • 其实我已经在 P.S. 中承认了这个问题。我刚刚建议你打开想象力,自己解决这个问题。解决方案很明显:在 browser.SetValue(...) 之前的 Browser_Navigated 处理程序中,您应该设置一些标志并在 browser.SetValue(...) 之后立即重置它。然后在 BindableSourcePropertyChanged 处理程序中,如果设置了此标志,您应该跳过更改 BindableSourceProperty。正确的方法是公开另一个附加属性,但在上面的示例中,我使用 Tag 属性实现了预期结果。
    • 谢谢。这个解决方案今天帮助了我。
    猜你喜欢
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 2015-12-04
    相关资源
    最近更新 更多