2009-05-08 57 views
14

Bu soruyu yazma başlamadan önce, ben bir iframe bir web sayfasında varsa her belge tamamlandıktan sonra, DocumentCompleted olay (daha sonra bir kez daha kovulacak olacağını, sorununWebBrowser denetimi nasıl kullanılır DocumentCompleted olayı C#?

// 1. navigate to page 
// 2. wait until page is downloaded 
// 3. read and write some data from/to iframe 
// 4. submit (post) form 

aşağıdaki çözmeye edildi çalışıyordu). Programın tamamlanmamış ve doğal olarak başarısız olan DOM verilerini okumayı denemesi büyük olasılıktı.

Ama bu soruyu yazarken aniden iken canavar 'ne' bana ilham ve ben çözmeye çalıştığını, sorunun fix'ed. Bunu Google’da başarısızlıkla karşılaştığımda, burada yayınlamanın güzel olacağını düşündüm.

private int iframe_counter = 1; // needs to be 1, to pass DCF test 
    public bool isLazyMan = default(bool); 

    /// <summary> 
    /// LOCK to stop inspecting DOM before DCF 
    /// </summary> 
    public void waitPolice() { 
     while (isLazyMan) Application.DoEvents(); 
    } 

    private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) { 
     if(!e.TargetFrameName.Equals("")) 
      iframe_counter --; 
     isLazyMan = true; 
    } 

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { 
     if (!((WebBrowser)sender).Document.Url.Equals(e.Url)) 
      iframe_counter++; 
     if (((WebBrowser)sender).Document.Window.Frames.Count <= iframe_counter) {//DCF test 
      DocumentCompletedFully((WebBrowser)sender,e); 
      isLazyMan = false; 
     } 
    } 

    private void DocumentCompletedFully(WebBrowser sender, WebBrowserDocumentCompletedEventArgs e){ 
     //code here 
    } 

Şu an için en azından 5m kesmek iyi çalışıyor gibi görünüyor.

Belki de google veya MSDN sorgulamada başarısız, ancak bulamıyorum: "C# Webbrowser denetimi DocumentCompleted olay nasıl kullanılır?"

Yorum: Webcontrol hakkında çok şey öğrendikten sonra, FuNKY şeyler yaptığını buldum.

Belgenin tamamlandığını algılasanız bile, çoğu durumda sonsuza kadar böyle kalmayacak. Sayfa güncellemesi çeşitli şekillerde yapılabilir: çerçeve yenileme, istek gibi ajax veya sunucu tarafı itme (senkronize olmayan iletişimi destekleyen bazı kontrollere sahip olmanız ve html veya JavaScript birlikte çalışması gerekir). Ayrıca bazı iframe'ler asla yüklenmez, bu yüzden sonsuza dek onları beklemek en iyi fikir değildir.

if (e.Url != wb.Url) 
+0

DocumentCompleted olayı sırasında IsBusy özelliğinin durumu nedir? – AMissico

+0

IsBusy, ilk kare hazır olduğunda false değerini döndürür. – Margus

+1

Sadece bir not, kodunuz çok normal çerçevelerle çalışmaz. –

cevap

14

AJAX çağrılarını da bilmek isteyebilirsiniz.

private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
{ 
    string url = e.Url.ToString(); 
    if (!(url.StartsWith("http://") || url.StartsWith("https://"))) 
    { 
      // in AJAX 
    } 

    if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath) 
    { 
      // IFRAME 
    } 
    else 
    { 
      // REAL DOCUMENT COMPLETE 
    } 
} 
+2

+1, ancak diğer kısım, GERÇEK BELGE TAMAMINI içeriyorsa, burada IFRAME – pug

+0

@ pug olması durumunda, bunu belirtmek için gönderiyi düzenledim. – AaronLS

0

Benzer bir şey yapmak zorunda:

kullanıyorum sona erdi. Yaptığım şey doğrudan ShDocVw kullanmasıdır (projeme gerekli tümleşik derlemeler için bir başvuru eklemek). Sonra, WebBrowser denetimi, formum için değil, AXShDocVw.AxWebBrowser denetimini eklemiyorum.

gezinmek ve aşağıdaki yönteme kullanmak beklemek için:

private void GotoUrlAndWait(AxWebBrowser wb, string url) 
{ 
    object dummy = null; 
    wb.Navigate(url, ref dummy, ref dummy, ref dummy, ref dummy); 

    // Wait for the control the be initialized and ready. 
    while (wb.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE) 
     Application.DoEvents(); 
} 
+2

Sadece bir not, sayfa asla "Komple" olmayacak gibi, Ajax kullanarak sayfa başarısız olur. –

3

İnternetten soruna bir çalışma çözüm bulmak için henüz. İnşallah bu, onu en üst seviyeye çıkaracak ve çözmeyi denediğim ayları ve onunla ilişkili kenar durumları herkesi kurtaracak. Microsoft, isBusy ve document.readystate'ın uygulama/güvenilirliğini değiştirdiği için yıllar içinde bu konu üzerinde mücadele ettim. IE8 ile, aşağıdaki çözüme başvurmak zorunda kaldım. Birkaç istisna dışında Margus'un sorusu/cevabıyla benzer. Kodum, iç içe çerçeveler, javascript/ajax istekleri ve meta yönlendirmeleri ele alacaktır. Netlik için kodu basitleştirdim, ancak 5 dakika domAccess hala yanlışsa sonra web sayfasını sıfırlamak için bir zaman aşımı işlevi (dahil değildir) kullanıyorum.

private void m_WebBrowser_BeforeNavigate(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel) 
{ 
    //Javascript Events Trigger a Before Navigate Twice, but the first event 
    //will contain javascript: in the URL so we can ignore it. 
    if (!URL.ToString().ToUpper().StartsWith("JAVASCRIPT:")) 
    { 
     //indicate the dom is not available 
     this.domAccess = false; 
     this.activeRequests.Add(URL); 
    } 
} 

private void m_WebBrowser_DocumentComplete(object pDisp, ref object URL) 
{ 

    this.activeRequests.RemoveAt(0); 

    //if pDisp Matches the main activex instance then we are done. 
    if (pDisp.Equals((SHDocVw.WebBrowser)m_WebBrowser.ActiveXInstance)) 
    { 
     //Top Window has finished rendering 
     //Since it will always render last, clear the active requests. 
     //This solves Meta Redirects causing out of sync request counts 
     this.activeRequests.Clear(); 
    } 
    else if (m_WebBrowser.Document != null) 
    { 
     //Some iframe completed dom render 
    } 

    //Record the final complete URL for reference 
    if (this.activeRequests.Count == 0) 
    { 
     //Finished downloading page - dom access ready 
     this.domAccess = true; 
    } 
} 
+0

, belki de önceki IE sürümlerindeki farklılıklara bakabilir miydiniz? – peterchen

+1

Webbrowser otomasyonunun ilk yıllarında sadece belge tamamlama işlevini kullanabildim - bu, 2002/3 civarındaydı - yani5.5/6. Eğer pdisp nesneniz üstteki belge penceresine uyuyorsa, belge tamamen hazırdı ve her zaman ateşlendi. Bu günlerde ateşlendiğinde, belgenizin hazır olduğundan emin olabilirsiniz, ancak büyük bir verimsiz zaman aşımına uğramayan bir asenkron olay modelinde bir olayın gerçekleşmediğini nasıl anlarsınız? IsBusy, fare imlecini değiştirmek için iyi bir gösterge olarak kullanılıyordu, ancak 7 ve 8'in son sürümünde IsBusy'nin sonsuza kadar gerçekte kaldığını gördüm. –

+0

Ve eğer doğru hatırlıyorsam AJAX istekleri bu olayı IE6'ya kadar düzgün bir şekilde tetiklemedi ve ie7 veya ie8 şimdi olayları seyretmeden önce kopyaları tetiklerler. Gezinme yaşam döngüsünün tamamlanma durumunu belirlemede size yardımcı olamayacakları için eksiksiz gezinme veya eksiksiz etkinlik indirme ile uğraşmayın. –

2

Thorsten aksine ben Shdocvw kullanmak zorunda değildi, ama bana readyState kontrol döngü ekleme ve Uygulama kullanıyordum için fark yaptıklarını:

bu kullanmayı düşünün.DoEvents() hazır değilken. İşte benim kodudur:

 this.webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted); 
     foreach (var item in this.urlList) // This is a Dictionary<string, string> 
     { 
      this.webBrowser.Navigate(item.Value); 
      while (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete) 
      { 
       Application.DoEvents(); 
      } 
     } 

Ve/else kullanıcının yorumun başına takas eğer son ile olsa WebBrowser_DocumentCompleted sonuçlarını kontrol etmek için Yuki çözümünü kullandı:

 private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
    { 
     string url = e.Url.ToString(); 
     var browser = (WebBrowser)sender; 

     if (!(url.StartsWith("http://") || url.StartsWith("https://")))  
     {    
      // in AJAX  
     } 
     if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath)  
     { 
      // IFRAME   
     }  
     else  
     {    
      // REAL DOCUMENT COMPLETE 
      // Put my code here 
     } 
    } 

bir cazibe gibi çalıştı :)

-1

Sadece bir çizgi ya da iki FeiBao kodu ile birlikte çalışan küçük bir gelişme hakkında düştü düşündüm. Buradaki fikir, web sayfasında bir yer işareti (javascript) değişkeni enjekte etmek ve sonraki DocumentComplete olaylarından hangisinin gerçek anlaşma olduğunu saptamaktır. Kurşun geçirmez olduğundan şüphe duyuyorum ama genel olarak eksik olan yaklaşımdan daha güvenilir bir şekilde çalıştı. Herhangi bir yorum hoşgeldiniz. İşte bu belge kodu:

void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
    { 
     string url = e.Url.ToString(); 
     var browser = (WebBrowser)sender; 

     if (!(url.StartsWith("http://") || url.StartsWith("https://"))) 
     { 
      // in AJAX  
     } 
     if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath) 
     { 
      // IFRAME   
     } 
     else if (browser.Document != null && (bool)browser.Document.InvokeScript("eval", new object[] { @"typeof window.YourLandMarkJavascriptVariableHere === 'undefined'" })) 
     { 
      ((IHTMLWindow2)browser.Document.Window.DomWindow).execScript("var window.YourLandMarkJavascriptVariableHere = true;"); 

      // REAL DOCUMENT COMPLETE 
      // Put my code here 
     } 
    }