【问题标题】:c# webBrowser.Document: reloading page after postbackc# webBrowser.Document:回发后重新加载页面
【发布时间】:2011-07-07 07:10:26
【问题描述】:

我正在开发一个简单的应用程序,它可以自动在包含两个下拉菜单和一个按钮的页面中浏览。页面如下所示:

-----DropDown1--------

-----DropDown2--------

-------按钮---------

现在的问题是,DropDown2 的内容是通过选择Dropdown1 动态生成的。

我用c#写了这样的代码:

private void webBrowser1_DocumentCompleted(object sender, 
        WebBrowserDocumentCompletedEventArgs e)
{
    HtmlElement elem = webBrowser1.Document.GetElementById("DropDown1");
    elem.SetAttribute("selectedIndex", "1");
    elem.RaiseEvent("onChange");
    HtmlElement elem = webBrowser1.Document.GetElementById("DropDown2");
    elem.SetAttribute("selectedIndex", "5");
    elem.RaiseEvent("onChange");
}

引发onChange 事件后,浏览器会加载新值,但我无法获取和设置DropDown2 值,因为文档仍然认为DropDown2s 值是空的。

如何获取和设置DropDown2 中生成的新值?

【问题讨论】:

    标签: c# html webbrowser-control


    【解决方案1】:

    我通过在引发 onChange 事件后调用“__doPostBack”脚本找到了解决方案。当我调用 doPostBack 时,文档会重新加载,因此我可以检索新值。代码如下:

        private void BeginOperation()
        {
            webBrowser1.Navigate("somewebpage", false);
            Task = 0;
        }
        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            HtmlElement elem;
    
            switch (Task)
            {
                case 0:
                    //HtmlDocument mydoc = webBrowser1.Document;
                     elem = webBrowser1.Document.GetElementById("ddlCity");
                    MessageBox.Show(elem.All.Count.ToString());
                    elem.SetAttribute("selectedIndex", "1");
                    //elem.RaiseEvent("onChange");
                    object[] args = {"someparameters"};
                    webBrowser1.Document.InvokeScript("__doPostBack",args);
                    Task++;
                break;
                case 1:
                    elem = webBrowser1.Document.GetElementById("ddlDistrict");
                    elem.SetAttribute("selectedIndex", "2");
                    elem.RaiseEvent("onChange");
                    object[] args2 = {"someparameters"};
                    webBrowser1.Document.InvokeScript("__doPostBack",args2);
                    Task++;
                break;
            }
         }
    

    【讨论】:

      【解决方案2】:

      我怀疑您遇到的问题是因为您编写的代码没有等待回发发生。那么会发生什么......

      |---> 页面完成加载,触发 DocumentCompleted 方法 |---> 你在 DropDown1 上设置了 selectedIndex |---> 你引发了 DropDown1 的 onChange 事件 | |---> 页面开始回发 (1) |---> 您(尝试)在 DropDown2 上设置 selectedIndex |---> 你引发了 DropDown2 的 onChange 事件 | |---> 页面开始回发 (2) | ... ... ... |---> 页面完成从回发 (2) 重新加载

      基本上,您需要做的是在触发回发后等待页面重新加载。这样做的不雅、脆弱且几乎肯定会中断/不起作用的方法是触发Timer 或类似的,以便在一段时间后(只要回发发生)您可以继续设置DropDown2 的 selectedIndex。更好的选择是这样做:

      |---> 页面完成加载,触发 DocumentCompleted 方法 |---> 您将一个新的 EventHandler 附加到 DocumentCompleted,其中包含 |用于更改 DropDown2 上的 selectedIndex 并删除它的代码 |事件处理程序 |---> 你在 DropDown1 上设置了 selectedIndex |---> 你引发了 DropDown1 的 onChange 事件 |---> DocumentCompleted 处理程序中的代码完成执行 |---> // 这是您在上面分配的 DocumentCompleted 处理程序 |---> 你在 DropDown2 上设置了 selectedIndex |---> 你引发了 DropDown2 的 onChange 事件 |---> DocumentCompleted 处理程序中的代码完成执行

      有更优雅的方法可以做到这一点,但这可能是最简单的解释。

      【讨论】:

      • 我也想过,但是“DocumentCompleted”处理程序在回发后没有运行。在 dropDown1 中选择一个项目只会触发一个填充 DropDown2 的函数。所以 Documentcompleted 被触发一次。还有一点需要注意的是,当我在 onChange 之后使用 System.Threading.Thread.Sleep(5000) 延迟时;线程只是等待完成回发 5 秒,但它不起作用.. 还有其他建议吗?
      【解决方案3】:

      谢谢你。几天来我一直在寻找类似问题的解决方案... 就我而言,我有一个下拉菜单,其中列表中的项目在“onchange”事件期间更新。调用 __doPostBack 更新 WebBrowserReadyState 允许我在抓取新的下拉列表值之前等待“onchange”事件完成。

      【讨论】:

      • 不客气,很高兴能帮上忙
      猜你喜欢
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-08
      相关资源
      最近更新 更多