2014-03-26 139 views
0

我在Windows窗體項目中有WebBrowser。它導航表格元素中的所有鏈接。它工作正常;但是它在迴路中使用break。如何在沒有break聲明的情況下實現此功能?如何避免循環中斷?

注意:在我的真實場景中,如果我們給出帶有該鏈接的導航命令,所有鏈接將重定向到登錄頁面。因此,在我的實際場景中,存儲所有網址並在之後執行導航操作對我來說不起作用。

C#代碼

public partial class Form1 : Form 
{ 

string websiteUrl = @"C:\Samples_L\MyTableTest.html"; 
List<string> visitedUrls = new List<string>(); 
string currentUrl = String.Empty; 

private void ExerciseApp(object sender, EventArgs e) 
{ 

    Thread.Sleep(1000); 

    if (currentUrl != websiteUrl) 
    { 
     currentUrl = websiteUrl; 
     wb.Navigate(websiteUrl); 
    } 


    HtmlElement tableElement = wb.Document.GetElementById("four-grid"); 
    if (tableElement != null) 
    { 
     foreach (HtmlElement e1 in tableElement.All) 
     { 
      string x = e1.TagName; 
      String idStr = e1.GetAttribute("id"); 

      if (!String.IsNullOrWhiteSpace(idStr)) 
      { 
       if (idStr.Contains("catalogEntry_img")) 
       { 
        string url = e1.GetAttribute("href"); 
        if (!visitedUrls.Contains(url)) 
        { 
         currentUrl = url; 
         visitedUrls.Add(url); 
         e1.InvokeMember("Click"); 

         //Use break when the first match is found 
         break; 
        } 
       } 
      } 
     } 
    } 

} 



private System.Windows.Forms.WebBrowser wb = null; 
private Button button1 = null; 
private ListBox listBox1 = null; 

public Form1() 
{ 

    // button1 
    button1 = new Button(); 
    button1.Location = new Point(20, 430); 
    button1.Size = new Size(90, 23); 
    button1.Text = "Load and Test"; 
    button1.Click += new EventHandler(this.button1_Click); 

    // listBox1 
    listBox1 = new ListBox(); 
    listBox1.Location = new Point(10, 460); 
    listBox1.Size = new Size(460, 200); 

    // Web Browser 
    wb = new WebBrowser(); 
    wb.Location = new Point(10, 10); 
    wb.Size = new Size(1000, 400); 

    //Subscribing for the Document Completed Event 
    wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(ExerciseApp); 

    // Form1 
    this.Text = "Web Browser Test"; 
    this.Size = new Size(5000, 7100); 
    this.Controls.Add(wb); 
    this.Controls.Add(button1); 
    this.Controls.Add(listBox1); 

    currentUrl = websiteUrl; 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    listBox1.Items.Add("Loading Web app under test into WebBrowser control"); 
    wb.Url = new Uri(websiteUrl); 

} 


} 

使用HTML

<html> 
<head> 

    <style type="text/css"> 
     table { 
      border: 2px solid blue; 
     } 

     td { 
      border: 1px solid teal; 
     } 
    </style> 

</head> 
<body> 

    <table id="four-grid"> 
     <tr> 
      <td> 
       <a href="https://stackoverflow.com/users/696627/lijo" id="catalogEntry_img63664" class="itemhover" 
        onfocus="showPopupButton('category_63664');" 
        onkeydown="shiftTabHidePopupButton('category_63664',event);"> 

        <img src="ssss" 
         alt="G" width="70" /> 
       </a> 
      </td> 
      <td> 
       <a href="http://msdn.microsoft.com/en-US/#fbid=zgGLygxrE84" id="catalogEntry_img63665" class="itemhover" 
        onfocus="showPopupButton('category_63665');" 
        onkeydown="shiftTabHidePopupButton('category_63665',event);"> 

        <img src="ssss" 
         alt="Y" width="70" /> 
       </a> 
      </td> 
     </tr> 
     <tr> 
      <td> 
       <a href="https://www.wikipedia.org/" id="catalogEntry_img63666" class="itemhover" 
        onfocus="showPopupButton('category_63666');" 
        onkeydown="shiftTabHidePopupButton('category_63666',event);"> 

        <img src="ssss" 
         alt="B" width="70" /> 
       </a> 
      </td> 
      <td> 
       <a href="http://www.keralatourism.org/" id="catalogEntry_img63667" class="itemhover" 
        onfocus="showPopupButton('category_63667');" 
        onkeydown="shiftTabHidePopupButton('category_63667',event);"> 

        <img src="ssss" 
         alt="A" width="70" /> 
       </a> 
      </td> 
     </tr> 
    </table> 
</body> 

</html> 

參考

  1. Next using LINQ approach
+5

爲什麼要刪除break語句? –

+0

迭代你自己而不是使用foreach,並且當你不得不休息時保持一個等於true的bool變量。在循環條件中,檢查你是否有更多的元素,並且這個布爾變量仍然是假的 –

+0

參考[在for循環中使用break是不好的做法?](http://stackoverflow.com/questions/3922599/is -it-a-bad-practice-to-use-break-in-a-for-loop) – Lijo

回答

4

你可以重構它到一個查詢,使代碼的意圖更爲清楚:

var nextElement = tableElement.All 
    .Where(element => element.GetAttribute("id") != null && 
     element.GetAttribute("id").Contains("catalogEntry_img") && 
     !visitedUrls.Contains(element.GetAttribute("href"))) 
    .FirstOrDefault(); 

if(nextElement != null) 
{ 
    visitedUrls.Add(nextElement.GetAttribute("href")); 
    nextElement.InvokeMember("Click"); 
    currentUrl = nextElement.GetAttribute("href"); 
} 

我也建議改變visitedUrlsHashSet,而不是一個列表,因爲它是一個更高效的數據結構,用於簡單確定項目是否在一組項目中。

+0

這也使用休息 - 它只是隱藏它:) – Danvil

+1

@Danvil [不,實際上它沒有。](http://referencesource.microsoft.com/#System .Core/System/Linq/Enumerable.cs#8087366974af11d2)即使它確實存在,那也不是那麼重要。您不負責維護'FirstOrDefault'。 MS將確保它能夠正常工作。在引擎蓋下,所有循環都使用GOTO。這沒有錯,但這並不意味着你應該使用GOTO。在構建工具/抽象層時,使用低級工具*,以便其他代碼可以使用高級工具*,並避免使用低級工具的麻煩。 – Servy

+1

@Danvil誰在乎?編譯器使用'goto',但隱藏它。重要的一點是「隱藏它」。即使'break'仍然被使用,但是被隱藏,它所創造的感知混亂(或者OP使用的任何參數)被刪除,因爲它已被抽象化。 –

0

如果迭代值的範圍,並希望一旦你找到了一個滿足條件退出,是很常見的使用break:

foreach(var a in list) { 
    if(test(a)) { 
     // use a 
     break; 
    } 
} 

有時可能是不需要的,你可以直接使用此:

bool found = false; 
foreach(var a in list) { 
    if(found && test(a)) { 
     // use a 
     found = true; 
    } 
} 

甚至:

bool found = false; 
foreach(var a in list) { 
    if(test(a)) { 
     if(found) { 
      // use a 
      found = true; 
     } 
    } 
} 

第一個版本可以跳過它一旦找到合適的元素就會發生。其他兩個變體不斷迭代或甚至檢查所有元素。在幾乎所有情況下,這隻會浪費處理能力。但在這裏看看你實際上可能想要使用第三個變體的情況:http://en.wikipedia.org/wiki/Timing_attack