2008-10-31 33 views
33

如果我想在ASP.NET頁面上查找複選框,我可以使用以下LINQ查詢。使用LINQ進行遞歸控制搜索

var checkBoxes = this.Controls 
        .OfType<CheckBox>() 
        .TakeWhile<CheckBox>(cb => cb.Checked); 

,如果複選框被嵌套在電流控制收集工作正常,但我想知道如何通過向下鑽取到頂層控制的控制集合來擴展搜索。

的問題在這裏問:

Finding controls that use a certain interface in ASP.NET

而收到的非LINQ的答案,我已經有我自己的類型和ID作爲擴展方法遞歸控制搜索的版本,但我只是想知道容易這是在LINQ做什麼?

回答

43

取出遞歸類型/ ID檢查,所以只需要「給我所有控制,遞歸」方法,例如,

public static IEnumerable<Control> GetAllControls(this Control parent) 
{ 
    foreach (Control control in parent.Controls) 
    { 
     yield return control; 
     foreach(Control descendant in control.GetAllControls()) 
     { 
      yield return descendant; 
     } 
    } 
} 

這有點低效(在創造大量的迭代器而言),但我懷疑,你將有一個非常樹。

然後你可以寫你的原始查詢爲:

var checkBoxes = this.GetAllControls() 
        .OfType<CheckBox>() 
        .TakeWhile<CheckBox>(cb => cb.Checked); 

(編輯:改變AllControls到GetAllControls和正確地使用它作爲一種方法)

+0

這樣的作品,但如果你是使用第三方控件和您自己的服務器控件,我們在我目前的工作場所做,你可以得到很好的控制嵌套層次。我想ASP.NET頁面只是一個更常見問題的例子,即通過Linq中的嵌套集合進行深入研究。 – PhilGriffin 2008-10-31 15:52:20

0

我的建議,使AllControls遞歸是:

public static IEnumerable<Control> AllControls(this Control parent) 
    { 
     foreach (Control control in parent.Controls) 
     { 
      yield return control; 
     } 
     foreach (Control control in parent.Controls) 
     { 
      foreach (Control cc in AllControls(control)) yield return cc; 
     } 
    } 

第二個foreach看起來很奇怪,但這是我知道「扁平化」遞歸調用的唯一方法。

2
public static IEnumerable<Control> AllControls(this Control container) 
{ 
    //Get all controls 
    var controls = container.Controls.Cast<Control>(); 

    //Get all children 
    var children = controls.Select(c => c.AllControls()); 

    //combine controls and children 
    var firstGen = controls.Concat(children.SelectMany(b => b)); 

    return firstGen; 
} 

現在基於上述功能,我們可以做這樣的事情:

public static Control FindControl(this Control container, string Id) 
{ 
    var child = container.AllControls().FirstOrDefault(c => c.ID == Id); 
    return child; 
}