2013-08-21 20 views
5

Ho un controllo WebBrowser in WinForms la cui proprietà URL è impostata su una pagina Web esterna. Ho anche un gestore di eventi per l'evento DocumentCompleted. All'interno di questo gestore, sto cercando di ottenere elementi specifici, ma wb.Document.Body sembra catturare l'HTML prima che l'onload venga eseguito.Ottenere il contenuto del corpo HTML in WinForms WebBrowser dopo l'evento onload del corpo viene eseguito

{System.Windows.Forms.HtmlElement} 
    All: {System.Windows.Forms.HtmlElementCollection} 
    CanHaveChildren: true 
    Children: {System.Windows.Forms.HtmlElementCollection} 
    ClientRectangle: {X = 0 Y = 0 Width = 1200 Height = 0} 
    Document: {System.Windows.Forms.HtmlDocument} 
    DomElement: {mshtml.HTMLBodyClass} 
    ElementShim: {System.Windows.Forms.HtmlElement.HtmlElementShim} 
    Enabled: true 
    FirstChild: null 
    htmlElement: {mshtml.HTMLBodyClass} 
    Id: null 
    InnerHtml: "\n" 
    InnerText: null 
    Name: "" 
    NativeHtmlElement: {mshtml.HTMLBodyClass} 
    NextSibling: null 
    OffsetParent: null 
    OffsetRectangle: {X = 0 Y = 0 Width = 1200 Height = 0} 
    OuterHtml: "<body onload=\"evt_Login_onload(event);\" uitheme=\"Web\">\n</body>" 
    OuterText: null 
    Parent: {System.Windows.Forms.HtmlElement} 
    ScrollLeft: 0 
    ScrollRectangle: {X = 0 Y = 0 Width = 1200 Height = 0} 
    ScrollTop: 0 
    shimManager: {System.Windows.Forms.HtmlShimManager} 
    ShimManager: {System.Windows.Forms.HtmlShimManager} 
    Style: null 
    TabIndex: 0 
    TagName: "BODY" 

"<body onload=\"evt_Login_onload(event);\" uitheme=\"Web\">\n</body>" è il contenuto pre-JavaScript. Esiste un modo per acquisire lo stato del tag body dopo l'esecuzione di evt_Login_onload(event);?

Ho anche provato a utilizzare wb.Document.GetElementById("id"), ma restituisce null.

risposta

6

Ecco come si può fare, ho messo un po 'di commenti in linea:

private void Form1_Load(object sender, EventArgs e) 
{ 
    bool complete = false; 
    this.webBrowser1.DocumentCompleted += delegate 
    { 
     if (complete) 
      return; 
     complete = true; 
     // DocumentCompleted is fired before window.onload and body.onload 
     this.webBrowser1.Document.Window.AttachEventHandler("onload", delegate 
     { 
      // Defer this to make sure all possible onload event handlers got fired 
      System.Threading.SynchronizationContext.Current.Post(delegate 
      { 
       // try webBrowser1.Document.GetElementById("id") here 
       MessageBox.Show("window.onload was fired, can access DOM!"); 
      }, null); 
     }); 
    }; 

    this.webBrowser1.Navigate("http://www.example.com"); 
} 
+1

+1 posso confermare questa risposta ha funzionato per me, anche se non ho avuto bisogno di usare 'SyncronizationContext.Current.Post() 'perché sto utilizzando un singolo thread. –

+0

@StevendeSalas, l'intero scopo di 'SyncronizationContext.Current.Post' era di ritornare dal gestore di eventi' onload' e continuare in modo asincrono sullo stesso thread dell'interfaccia utente (quindi eventuali eccezioni non verrebbero gettate all'interno del codice MSHTML che attiva l'evento). Da allora il codice si è evoluto un po 'per usare 'async' /' await' invece, [example] (http://stackoverflow.com/a/19063643/1768303). – Noseratio

+0

Ho provato un approccio simile, ma non ha funzionato .. Puoi dare un'occhiata http://stackoverflow.com/questions/22697987/form-become-blank-intermittently? – Lijo