Wpf WebBrowser刷新

我在我的项目中使用WebBrowser控件。

我注意到如果用户按下右键 – >刷新

Navigating

LoadCompleted

不叫。

另一个奇怪的事情是,在我按下刷新并单击webbrowser中的另一个链接之后, LoadCompleted没有被调用。

这就是我在开始时浏览页面的方式:

 nrowser.Navigate(MYPAGE); 

知道可能是什么问题吗?

我能用JavaScript修复它吗?

您可以处理刷新并将其与导航区分开来。 通过一些练习,可以通过处理DOM document.onreadystatechangewindow.onunload事件以及底层WebBrowser ActiveX控件的NavigateComplete2DownloadBegin事件来完成。

在刷新页面时, NavigateComplete2不会被顶层WebBrowser对象触发,但在导航时会触发。 对于任何下载,导航或刷新活动, DownloadBegin总是被解雇,可能多次。 window.onunload在导航或刷新之前被触发,而document.onreadystatechange在导航或刷新期间被触发。 其余的是跟踪状态转换的问题。 这是一个工作示例(仍可能包含错误)。

C#:

 using Microsoft.Win32; using System; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; namespace WpfWebBrowser { public partial class MainWindow : Window { bool navigating = false; bool loading = false; bool loaded = false; public MainWindow() { SetBrowserFeatureControl(); InitializeComponent(); this.Loaded += (s, e) => { var axWebBrowser = (SHDocVw.WebBrowser)GetActiveXInstance(this.webBrowser); axWebBrowser.DownloadBegin += delegate { HandleDownloadActivity(); }; axWebBrowser.NavigateComplete2 += delegate(object pDisp, ref object URL) { // top frame? if (Object.ReferenceEquals(axWebBrowser, pDisp)) { this.navigating = true; HandleDownloadActivity(); } }; this.webBrowser.Navigate("http://example.com"); }; } // handler for document.readyState == "complete" void DomDocumetCompleteHandler(dynamic domDocument) { dynamic domWindow = domDocument.parentWindow; domWindow.attachEvent("onunload", new DomEventHandler(delegate { this.loaded = false; this.loading = false; })); var navigated = this.navigating; this.navigating = false; this.loaded = true; this.loading = false; MessageBox.Show(navigated ? "Navigated" : "Refreshed"); } void HandleDownloadActivity() { dynamic domDocument = this.webBrowser.Document; if (domDocument == null) return; if (loading || loaded) return; this.loading = true; if (domDocument.readyState == "complete") { DomDocumetCompleteHandler(domDocument); } else { DomEventHandler handler = null; handler = new DomEventHandler(delegate { if (domDocument.readyState == "complete") { domDocument.detachEvent("onreadystatechange", handler); DomDocumetCompleteHandler(domDocument); } }); domDocument.attachEvent("onreadystatechange", handler); } } ///  /// Get the underlying WebBrowser ActiveX object; /// this code depends on SHDocVw.dll COM interop assembly, /// generate SHDocVw.dll: "tlbimp.exe ieframe.dll", /// and add as a reference to the project ///  static object GetActiveXInstance(WebBrowser wb) { return wb.GetType().InvokeMember("ActiveXInstance", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, wb, new object[] { }) as SHDocVw.WebBrowser; } ///  /// EventHandler - adaptor to call C# back from JavaScript or DOM event handlers ///  [ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch)] public class DomEventHandler { [ComVisible(false)] public delegate void Callback(ref object result, object[] args); [ComVisible(false)] private Callback _callback; [DispId(0)] public object Method(params object[] args) { var result = Type.Missing; // Type.Missing is "undefined" in JavaScript _callback(ref result, args); return result; } public DomEventHandler(Callback callback) { _callback = callback; } } ///  /// WebBrowser version control /// http://msdn.microsoft.com/en-us/library/ee330730(v=vs.85).aspx#browser_emulation ///  void SetBrowserFeatureControl() { // http://msdn.microsoft.com/en-us/library/ee330720(v=vs.85).aspx // FeatureControl settings are per-process var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName); // make the control is not running inside Visual Studio Designer if (String.Compare(fileName, "devenv.exe", true) == 0 || String.Compare(fileName, "XDesProc.exe", true) == 0) return; // Webpages containing standards-based !DOCTYPE directives are displayed in IE9/IE10 Standards mode. SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, 9000); } void SetBrowserFeatureControlKey(string feature, string appName, uint value) { using (var key = Registry.CurrentUser.CreateSubKey( String.Concat(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature), RegistryKeyPermissionCheck.ReadWriteSubTree)) { key.SetValue(appName, (UInt32)value, RegistryValueKind.DWord); } } } } 

XAML:

    

谢谢Noseratio,它很棒。 我将您所做的事情包装到一个对象中,您可以将Web浏览器传递到并处理事件。

 public class WebBrowserHook { private bool _isNavigating = false; private bool _isLoading = false; private bool _isLoaded = false; private WebBrowser _webBrowser = null; public WebBrowserHook(WebBrowser webBrowser) { _webBrowser = webBrowser; _webBrowser.Loaded += (s, e) => { try { var axWebBrowser = (SHDocVw.WebBrowser)GetActiveXInstance(this._webBrowser); axWebBrowser.DownloadBegin += delegate { HandleDownloadActivity(); }; axWebBrowser.NavigateComplete2 += delegate(object pDisp, ref object URL) { // top frame? if (Object.ReferenceEquals(axWebBrowser, pDisp)) { this._isNavigating = true; HandleDownloadActivity(); } }; } catch (Exception ex) { AppLog.LogException(ex); } }; } public event EventHandler Navigated; public event EventHandler Refreshed; public WebBrowser Browser { get{return _webBrowser;} } // handler for document.readyState == "complete" private void DomDocumentCompleteHandler(mshtml.HTMLDocument domDocument) { try { mshtml.HTMLWindow2 domWindow = (mshtml.HTMLWindow2)domDocument.parentWindow; domWindow.attachEvent("onunload", new DomEventHandler(delegate { this._isLoaded = false; this._isLoading = false; })); var navigated = this._isNavigating; this._isNavigating = false; this._isLoaded = true; this._isLoading = false; if (navigated) { if (Navigated != null) Navigated(this, new EventArgs()); } else { if (Refreshed != null) Refreshed(this, new EventArgs()); } } catch (Exception ex) { AppLog.LogException(ex); } } private void HandleDownloadActivity() { try { mshtml.HTMLDocument domDocument = (mshtml.HTMLDocument)this._webBrowser.Document; if (domDocument == null) return; if (_isLoading || _isLoaded) return; this._isLoading = true; if (domDocument.readyState == "complete") { DomDocumentCompleteHandler(domDocument); } else { DomEventHandler handler = null; handler = new DomEventHandler(delegate { if (domDocument.readyState == "complete") { domDocument.detachEvent("onreadystatechange", handler); DomDocumentCompleteHandler(domDocument); } }); domDocument.attachEvent("onreadystatechange", handler); } } catch (Exception ex) { AppLog.LogException(ex); } } ///  /// Get the underlying WebBrowser ActiveX object; /// this code depends on SHDocVw.dll COM interop assembly, /// generate SHDocVw.dll: "tlbimp.exe ieframe.dll", /// and add as a reference to the project ///  private static object GetActiveXInstance(WebBrowser wb) { return wb.GetType().InvokeMember("ActiveXInstance", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, wb, new object[] { }) as SHDocVw.WebBrowser; } ///  /// EventHandler - adaptor to call C# back from JavaScript or DOM event handlers ///  [ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch)] public class DomEventHandler { [ComVisible(false)] public delegate void Callback(ref object result, object[] args); [ComVisible(false)] private Callback _callback; [DispId(0)] public object Method(params object[] args) { var result = Type.Missing; // Type.Missing is "undefined" in JavaScript _callback(ref result, args); return result; } public DomEventHandler(Callback callback) { _callback = callback; } } }