当前位置:首 页 > 攻城湿 >Windows > 查看文章

WPF WebBrowser control – how to supress script errors?

Windows 你是第1883个围观者 0条评论 供稿者: 标签:, , ,

Thanks to Simon Mourier for elegant way to solve this problem. I made a little improvement and encapsulated Simon’s solution into attached property.

In my application I use WebBrowser control databounded to viewmodel, the webbrowser might be hidden on inactive TabItem, so I have to check that it has been Loaded and Navigated before setting javascript errors silent. And of cource this setting should be done just once, so after setting I release hooked events.

XAML Code:

<TabControl xmlns:b="clr-namespace:MyApplication.Behaviors">
  <TabItem Header="foo">...</TabItem>
  <TabItem Header="Google map">
    <WebBrowser b:BindableSource="{Binding Path=MapUrl}"
                b:DisableJavascriptErrors="True" />
  </TabItem>
</TabControl>

Behavior code:

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace MyApplication.Behaviors
{
    public class WebBrowserBehavior
    {
        private static readonly Type OwnerType = typeof (WebBrowserBehavior);

        #region BindableSource

        public static readonly DependencyProperty BindableSourceProperty =
            DependencyProperty.RegisterAttached(
                "BindableSource", 
                typeof(string), 
                OwnerType, 
                new UIPropertyMetadata(OnBindableSourcePropertyChanged));

        [AttachedPropertyBrowsableForType(typeof(WebBrowser))]
        public static string GetBindableSource(DependencyObject obj)
        {
            return (string)obj.GetValue(BindableSourceProperty);
        }

        [AttachedPropertyBrowsableForType(typeof(WebBrowser))]
        public static void SetBindableSource(DependencyObject obj, string value)
        {
            obj.SetValue(BindableSourceProperty, value);
        }

        public static void OnBindableSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var browser = d as WebBrowser;
            if (browser == null) return;

            browser.Source = (e.NewValue != null) ? new Uri(e.NewValue.ToString()) : null;
        }

        #endregion

        #region DisableJavascriptErrors

        #region SilentJavascriptErrorsContext (private DP)

        private static readonly DependencyPropertyKey SilentJavascriptErrorsContextKey =
            DependencyProperty.RegisterAttachedReadOnly(
                "SilentJavascriptErrorsContext",
                typeof (SilentJavascriptErrorsContext),
                OwnerType,
                new FrameworkPropertyMetadata(null));

        private static void SetSilentJavascriptErrorsContext(DependencyObject depObj, SilentJavascriptErrorsContext value)
        {
            depObj.SetValue(SilentJavascriptErrorsContextKey, value);
        }

        private static SilentJavascriptErrorsContext GetSilentJavascriptErrorsContext(DependencyObject depObj)
        {
            return (SilentJavascriptErrorsContext) depObj.GetValue(SilentJavascriptErrorsContextKey.DependencyProperty);
        }

        #endregion

        public static readonly DependencyProperty DisableJavascriptErrorsProperty =
            DependencyProperty.RegisterAttached(
                "DisableJavascriptErrors",
                typeof (bool),
                OwnerType,
                new FrameworkPropertyMetadata(OnDisableJavascriptErrorsChangedCallback));

        [AttachedPropertyBrowsableForType(typeof(WebBrowser))]
        public static void SetDisableJavascriptErrors(DependencyObject depObj, bool value)
        {
            depObj.SetValue(DisableJavascriptErrorsProperty, value);
        }

        [AttachedPropertyBrowsableForType(typeof(WebBrowser))]
        public static bool GetDisableJavascriptErrors(DependencyObject depObj)
        {
            return (bool)depObj.GetValue(DisableJavascriptErrorsProperty);
        }

        private static void OnDisableJavascriptErrorsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var webBrowser = d as WebBrowser;
            if (webBrowser == null) return;
            if (Equals(e.OldValue, e.NewValue)) return;

            var context = GetSilentJavascriptErrorsContext(webBrowser);
            if (context != null) {
                context.Dispose();
            }

            if (e.NewValue != null) {
                context = new SilentJavascriptErrorsContext(webBrowser);
                SetSilentJavascriptErrorsContext(webBrowser, context);
            }
            else {
                SetSilentJavascriptErrorsContext(webBrowser, null);
            }
        }

        private class SilentJavascriptErrorsContext : IDisposable
        {
            private bool? _silent; 
            private readonly WebBrowser _webBrowser;


            public SilentJavascriptErrorsContext(WebBrowser webBrowser)
            {
                _silent = new bool?();

                _webBrowser = webBrowser;
                _webBrowser.Loaded += OnWebBrowserLoaded;
                _webBrowser.Navigated += OnWebBrowserNavigated;
            }

            private void OnWebBrowserLoaded(object sender, RoutedEventArgs e)
            {
                if (!_silent.HasValue) return;

                SetSilent();
            }

            private void OnWebBrowserNavigated(object sender, NavigationEventArgs e)
            {
                var webBrowser = (WebBrowser)sender;

                if (!_silent.HasValue) {
                    _silent = GetDisableJavascriptErrors(webBrowser);
                }

                if (!webBrowser.IsLoaded) return;

                SetSilent();
            }

            /// <summary>
            /// Solution by Simon Mourier on StackOverflow
            /// http://stackoverflow.com/a/6198700/741414
            /// </summary>
            private void SetSilent()
            {
                _webBrowser.Loaded -= OnWebBrowserLoaded;
                _webBrowser.Navigated -= OnWebBrowserNavigated;

                // get an IWebBrowser2 from the document
                var sp = _webBrowser.Document as IOleServiceProvider;
                if (sp != null)
                {
                    var IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
                    var IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");

                    object webBrowser2;
                    sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out webBrowser2);
                    if (webBrowser2 != null)
                    {
                        webBrowser2.GetType().InvokeMember(
                            "Silent",
                            BindingFlags.Instance | BindingFlags.Public | BindingFlags.PutDispProperty,
                            null,
                            webBrowser2,
                            new object[] { _silent });
                    }
                }
            }

            [ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            private interface IOleServiceProvider
            {
                [PreserveSig]
                int QueryService([In] ref Guid guidService, [In] ref Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);
            }

            public void Dispose()
            {
                if (_webBrowser != null) {
                    _webBrowser.Loaded -= OnWebBrowserLoaded;
                    _webBrowser.Navigated -= OnWebBrowserNavigated;
                }
            }
        }

        #endregion

    }
}

Stack Overflow

这家伙很懒,什么都没写!

—— zhaorong

zhaorong
你可能也喜欢Related Posts
众说纷纭Comments
大眼 可爱 大笑 坏笑 害羞 发怒 折磨 快哭了 大哭 白眼 晕 流汗 困 腼腆 惊讶 憨笑 色 得意 骷髅 囧 睡觉 眨眼 亲亲 疑问 闭嘴 难过 淡定 抗议 鄙视 猪头
小提示:直接粘贴图片到输入框试试
努力发送中...
  • 评论最多
  • 最新评论
  • 随机文章
footer logo
未经许可请勿自行使用、转载、修改、复制、发行、出售、发表或以其它方式利用本网站之内容
Copyright © zhaorong All Rights Reserved. 滇ICP备15006105号-1