解决WebBrowser多次触发LoadCompleted事件的问题
一、起因
最近有个WPF的项目,需要频繁的加载不同的网页并提取网页的数据,随后就使用了WebBrowser控件。WPF使用WebBrowser控件获取网页,一般步骤是:
1、使用Navgiate方法或者WebBrowser的Source属性。
2、监听LoadCompleted事件,当该事件触发时,可以获取DOM。
由于我需要查看的网页比较多,需要依次向WebBrowser控件加载多个指定网址,随后获取各个DOM。一开始我是使用WithEvents来声明WebBrowser控件。但是随后发现会多次触发LoadCompleted事件。随着历史Navgiate方法的调用,该LoadCompleted事件会被越来越多的触发。
举个例子来说明:窗体加载时,首次调用Navgiate方法,导航到URL1,此时只会触发一次LoadCompleted;如果第二次调用Navgiate方法,导航到URL2,此时LoadCompleted将被触发2次,依次是URL1和URL2;依次类推,当加载很多次后,该事件将多次触发。
其实要避免这样的事情发生,可以通过手动绑定及解除LoadCompleted事件监听即可。我单独写了一个HtmlLoader类,来完成该操作,该类的详细代码如下:
二、HtmlLoader类模块
1 Imports mshtml 2 Public Class HtmlLoader 3 Private mWindow As Window 4 Private wb As WebBrowser 5 Private mURL As String 6 Public Property URL() As String 7 Get 8 Return mURL 9 End Get 10 Set(ByVal value As String) 11 mURL = value 12 End Set 13 End Property 14 15 Private mLoadCompleted As Boolean 16 17 Public Sub New(CurWindow As Window, webBrowser As WebBrowser) 18 mWindow = CurWindow 19 wb = webBrowser 20 End Sub 21 22 Public Sub New(CurWindow As Window, webBrowser As WebBrowser, URL As String) 23 mWindow = CurWindow 24 wb = webBrowser 25 Me.Reload(URL) 26 End Sub 27 28 Public Sub Reload() 29 mLoadCompleted = False 30 If Me.URL Is Nothing OrElse Me.URL.Trim.Length = 0 Then Exit Sub 31 mWindow.Dispatcher.Invoke(Sub() 32 LogNote.WriteLine(wb.Name & "-StartLoad", Me.URL) 33 AddHandler wb.LoadCompleted, AddressOf wb_LoadCompleted 34 'wb.Source = New Uri(Me.URL) 35 wb.Navigate(Me.URL) 36 End Sub) 37 End Sub 38 39 Public Sub Reload(URL As String) 40 Me.URL = URL 41 Reload() 42 End Sub 43 44 Private Sub wb_LoadCompleted(sender As Object, e As NavigationEventArgs) 45 mWindow.Dispatcher.Invoke(Sub() 46 LogNote.WriteLine(wb.Name & "-LoadCompleted", Me.URL) 47 RemoveHandler wb.LoadCompleted, AddressOf wb_LoadCompleted 48 End Sub) 49 mLoadCompleted = True 50 End Sub 51 52 Public Function GetDocument() As HTMLDocument 53 Do Until mLoadCompleted 54 55 Loop 56 Return mWindow.Dispatcher.Invoke(Function() As HTMLDocument 57 Return wb.Document 58 End Function) 59 End Function 60 End Class
三、说明
这个类接受WebBrowser控件所在窗体、WebBrowser控件对象及定位的URL做为参数。由于涉及到UI更新问题,需要使用Window对象的Dispatcher来操作,所以需要传递Window。
LogNote是我自己写的日志静态类,这里就不提供代码了,可以简单的将其注释掉就行了。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· .NET Core GC压缩(compact_phase)底层原理浅谈
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp
2016-10-10 C#研究OpenXML之路(2-DocumentFormat.OpenXml命名空间)