2011-03-02 16 views
5

Estoy trabajando en una aplicación simple que navega automáticamente en una página que contiene dos menús desplegables y un botón. La página tiene el siguiente aspecto:C# webBrowser.Document: página de recarga después de la devolución de datos

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

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

- ----- --------- botón

Ahora, el problema es que el contenido de DropDown2 se genera de forma dinámica por la selección de Dropdown1.

escribí código como este en 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"); 
} 

Después de levantar el evento onChange, el navegador carga los nuevos valores, pero no puedo obtener y establecer el valor DropDown2 porque el documento todavía piensa DropDown2 s valores están vacíos

¿Cómo puedo obtener y establecer los nuevos valores que se generan en DropDown2?

Respuesta

2

encontré la solución invocando el script "__doPostBack" después de generar el evento onChange. cuando invoco el doPostBack, el documento se vuelve a cargar y entonces puedo recuperar los nuevos valores. Aquí está el código:

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; 
     } 
    } 
0

Sospecho que el problema que está encontrando se debe a que el código que ha escrito no espera a que se produzca la devolución de datos. Así que lo que sucede es ....

 
|---> The page finishes loading, triggering your DocumentCompleted method 
|---> You set the selectedIndex on DropDown1 
|---> You raise the onChange event for DropDown1 
|  |---> The page starts posting-back (1) 
|---> You (attempt to) set the selectedIndex on DropDown2 
|---> You raise the onChange event for DropDown2 
|  |---> The page starts posting-back (2) 
| 
... 
... 
... 
|---> The page finishes re-loading from from postback (2) 

Básicamente, lo que hay que hacer es esperar después de activarse la devolución de datos de la página para volver a la carga. La manera poco elegante, frágil y casi segura de romper/no trabajar es activar Timer, o similar, de modo que después de un período de tiempo (siempre que tarde la devolución de datos) pueda continuar configurando el Índice seleccionado para DropDown2. La mejor opción sería la de hacer algo como esto:

 
|---> The page finishes loading, triggering your DocumentCompleted method 
|---> You attach a new EventHandler to DocumentCompleted that contains the 
|  code for changing the selectedIndex on DropDown2 and REMOVE this 
|  eventhandler 
|---> You set the selectedIndex on DropDown1 
|---> You raise the onChange event for DropDown1 
|---> Your code in the DocumentCompleted handler finishes executing 


|---> // This is the DocumentCompleted handler that you assign above 
|---> You set the selectedIndex on DropDown2 
|---> You raise the onChange event for DropDown2 
|---> Your code in the DocumentCompleted handler finishes executing 

Hay formas más elegantes de hacer esto, pero esto es probablemente la más simple de explicar.

+0

pensé en eso también pero Handler "DocumentCompleted" no se ejecuta después de la devolución. al seleccionar un elemento en dropDown1, solo se activa una función para completar DropDown2. así que Documentcompleted se dispara una vez. También otra nota, cuando pongo un retraso después de cambiar con System.Threading.Thread.Sleep (5000); el hilo solo espera terminar la devolución de datos durante 5 segundos y no funciona ... ¿Alguna otra sugerencia? – dreampowder

0

Gracias por esto. He estado buscando una solución a un problema similar por días ... En mi caso, tenía un único menú desplegable para el cual los elementos de la lista se actualizaban durante el evento "onchange". Invocando _ _doPostBack actualiza el WebBrowserReadyState, lo que me permite esperar hasta que se complete el evento "onchange" antes de raspar los nuevos valores de la lista desplegable.

+0

eres bienvenido, me alegro de poder ayudarte – dreampowder

Cuestiones relacionadas