【winform】基于UserControl实现webBrower组件时html页面元素加载及onclick事件监听实现
【背景】基于System.Windows.Forms.UserControl实现的webBrower组件在html内使用window.external调用winform事件失败。
【解决思路】借助winform的HtmlElementEventHandler完成html 页面元素点击时winform执行相应方法。
HTML
<input type="button" id="searchBtn" onclick="searchResource()"> <div id="resouceDetails" ></div> <input type="hidden" id="isLoading" data-val="Y">
JS
function searchResource(){ 1、$("#isLoading").val("N").attr("data-val","N"); 2、使用ajax向后台请求数据并拼接内容至resourceDetails $.ajax({ type : "post", url : 略l, data:略, dataType : "json", success: function(data) { var htmlStr=""; if(data.length>0){ for(var i=0,len=data.length;i<len;i++){ htmlStr+="<div data-class=\"rDetails\" data-id=\""+data[i].id+"\">"; htmlStr+="<img ; htmlStr+="</div>"; } } $("#resouceDetails").empty().append(htmlStr); } }); 3、$("#isLoading").val("N").attr("data-val","Y"); }
C#
winform监听searchBtn(搜索按钮)的onclick事件,并在searchResource()方法执行完毕后监听 div[data-class='rDetails']的点击事件并执行后续winform事件。
实现思路:
1、页面加载完毕后绑定searchBtn(搜索按钮)的onclick事件监听。
2、因winform无法判断js方法何时执行完毕,在searchResource()方法内借助隐藏域、在winform内启用Timer,Timer.Tick事件执行时判断:js是否执行完毕(隐藏域的 data-val==Y时js执行完毕)。
3、借助HtmlElement、HtmlElementCollection完成div[data-class='rDetails']的点击事件监听注册。
private Timer timer1 =null; public StudyResourceUCNew(){ InitializeComponent();this.webBrowser1.Navigate(LoadDataPath.loadResourceCenter()); this.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted); } /// <summary>
/// 网页加载完成的后续处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
HtmlDocument htmlDoc = webBrowser1.Document;
HtmlElement searchFrom=htmlDoc.All["searchForm"];
if(searchFrom!=null){
searchFrom.Click += new HtmlElementEventHandler(searchFrom_Click);
}
}
/// <summary> /// 监听搜索按钮 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void searchFrom_Click(object sender, EventArgs e) { timer1 = new Timer(); timer1.Interval = 100; timer1.Enabled = true; timer1.Tick += new EventHandler(timer1EventProcessor);//添加事件 } public void timer1EventProcessor(object sender, EventArgs e) { HtmlDocument htmlDoc = webBrowser1.Document; HtmlElement isLoading = htmlDoc.All["isLoading"]; //js拼接页面是否完成 if (isLoading.GetAttribute("data-val") == "Y") { timer1.Stop(); timer1.Tick -= new EventHandler(timer1EventProcessor); timer1 = null; //重新绑定资源的onclick事件 HtmlElement resouceDetails = htmlDoc.All["resouceDetails"]; HtmlElementCollection cells = resouceDetails.GetElementsByTagName("div"); for (var i = 0; i < cells.Count; i++) { var status = cells[i].GetAttribute("data-class"); if (status == "rDetails") { cells[i].Click += new HtmlElementEventHandler(showResourceDetial); } } } } /// <summary> /// 查看资源详情 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void showResourceDetial(object sender, EventArgs e) { //do something }
【问题】页面初次加载时需要执行searchResource()加载数据显示初始页面,js 执行searchResource()方法使用并不能触发HtmlElementEventHandler 监听。
代码调整:
void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { HtmlDocument htmlDoc = webBrowser1.Document; HtmlElement searchFrom=htmlDoc.All["searchForm"]; if(searchFrom!=null){ searchFrom.Click += new HtmlElementEventHandler(searchFrom_Click); //js执行的searchForm click事件无法被监听到,需手动启动事件绑定线程 timer1 = new Timer(); timer1.Interval = 100; timer1.Enabled = true; timer1.Tick += new EventHandler(timer1EventProcessor);//添加事件 } }
至此所有问题解决。
[ComVisibleAttribute(true)] public partial class StudyResourceUCNew : UserControl {
private Timer timer1 =null;
public StudyResourceUCNew() { InitializeComponent(); this.webBrowser1.Location=new Point(0,0); this.webBrowser1.Width = this.scrollPanel.Width; this.webBrowser1.Height = this.scrollPanel.Width; this.webBrowser1.Navigate(LoadDataPath.loadResourceCenter()); this.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted); }
/// <summary> /// 网页加载完成的后续处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { HtmlDocument htmlDoc = webBrowser1.Document; HtmlElement searchFrom=htmlDoc.All["searchForm"]; if(searchFrom!=null){ searchFrom.Click += new HtmlElementEventHandler(searchFrom_Click); //js执行的searchForm click事件无法被监听到,需手动启动事件绑定线程 timer1 = new Timer(); timer1.Interval = 100; timer1.Enabled = true; timer1.Tick += new EventHandler(timer1EventProcessor);//添加事件 } }
/// <summary> /// 监听搜索按钮 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void searchFrom_Click(object sender, EventArgs e) { timer1 = new Timer(); timer1.Interval = 100; timer1.Enabled = true; timer1.Tick += new EventHandler(timer1EventProcessor);//添加事件 }
public void timer1EventProcessor(object sender, EventArgs e) { HtmlDocument htmlDoc = webBrowser1.Document; HtmlElement isLoading = htmlDoc.All["isLoading"];
//js拼接页面是否完成 if (isLoading.GetAttribute("data-val") == "Y") { timer1.Stop(); timer1.Tick -= new EventHandler(timer1EventProcessor); timer1 = null;
//重新绑定资源的onclick事件 HtmlElement resouceDetails = htmlDoc.All["resouceDetails"]; HtmlElementCollection cells = resouceDetails.GetElementsByTagName("div"); for (var i = 0; i < cells.Count; i++) { var status = cells[i].GetAttribute("data-class"); if (status == "rDetails") { cells[i].Click += new HtmlElementEventHandler(showResourceDetial); } }
}
}
/// <summary> /// 查看资源详情 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void showResourceDetial(object sender, EventArgs e) { StudyReSourceForm fm = new StudyReSourceForm(); HtmlElement cell = (HtmlElement)sender; fm.CurClickResourceID = int.Parse(cell.GetAttribute("data-id")); MyShowDialog.MyShowDialogFunc2(fm, this.FindForm()); } }