LINQを使用した再帰制御検索
-
05-07-2019 - |
質問
ASP.NETページでチェックボックスを検索する場合、次のLINQクエリを使用できます。
var checkBoxes = this.Controls
.OfType<CheckBox>()
.TakeWhile<CheckBox>(cb => cb.Checked);
チェックボックスが現在のコントロールコレクションにネストされている場合は正常に機能しますが、トップレベルコントロールのコントロールコレクションにドリルダウンして検索を拡張する方法を知りたいです。
ここで質問されました:
ASP.NETの特定のインターフェイスを使用するコントロールの検索
非LINQの回答を受け取りました。拡張メソッドとして型とIDの再帰制御検索の独自バージョンを既に持っていますが、LINQでこれを行うのがどれほど簡単か疑問に思いました。
解決
型/ 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に変更し、メソッドとして適切に使用します。)
他のヒント
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;
}
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;
}
}
2番目の foreach
は奇妙に見えますが、これが私が「平坦化」する唯一の方法です。再帰呼び出し。
所属していません StackOverflow