Recursive control search with LINQ
Jeśli chciałem znaleźć zaznaczone pola wyboru na ASP.NET page I could use the following LINQ query.
var checkBoxes = this.Controls
.OfType<CheckBox>()
.TakeWhile<CheckBox>(cb => cb.Checked);
To działa dobrze, jeśli pola wyboru są zagnieżdżone w bieżącej kolekcji kontroli, ale chciałbym wiedzieć, jak Rozszerzyć wyszukiwanie, wiercąc w dół do kolekcji kontroli najwyższego poziomu.
Pytanie zostało zadane tutaj:
Znajdowanie kontrolek, które używają określonego interfejsu w ASP.NET
I otrzymałem odpowiedzi nie LINQ, już mam moja własna wersja rekurencyjnego wyszukiwania kontrolnego na type i ID jako metody rozszerzenia, ale zastanawiałem się, jak łatwo to zrobić w LINQ?
3 answers
Weź Typ / ID z rekurencji, więc po prostu miej metodę "daj mi wszystkie kontrolki, rekurencyjnie", np.
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;
}
}
}
To trochę nieefektywne (jeśli chodzi o tworzenie wielu iteratorów), ale wątpię, że będziesz miał bardzo głębokie drzewo.
Możesz następnie napisać swoje oryginalne zapytanie jako:
var checkBoxes = this.GetAllControls()
.OfType<CheckBox>()
.TakeWhile<CheckBox>(cb => cb.Checked);
(EDIT: zmieniono Ustawienia AllControls na GetAllControls i używaj ich jako metody.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 16:06:52
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;
}
Teraz na podstawie powyższej funkcji możemy zrobić coś takiego:
public static Control FindControl(this Control container, string Id)
{
var child = container.AllControls().FirstOrDefault(c => c.ID == Id);
return child;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 15:55:04
Moja sugestia, aby AllControls
rekurencyjny jest:
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;
}
}
Drugi foreach
wygląda dziwnie, ale jest to jedyny sposób, jaki znam, aby "spłaścić" wywołanie rekurencyjne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 15:53:23