Этот способ превосходит метод MSDN в том смысле, что его можно использовать повторно, и он позволяет досрочно прервать цикл (т. Е. С помощью break;
и т. Д.) - он оптимизирует цикл for, поскольку сохраняет вызов метода для каждой итерации - и это также позволяет вам использовать обычные циклы for для циклического обхода дочерних элементов Visual или даже повторять его дочерние и внучатые дочерние элементы - так что его намного проще потреблять.
Чтобы использовать его, вы можете просто написать обычный цикл foreach (или даже использовать LINQ):
foreach (var ctrl in myWindow.GetChildren())
{
// Process children here!
}
Или, если вы не хотите возвращаться:
foreach (var ctrl in myWindow.GetChildren(false))
{
// Process children here!
}
Чтобы заставить его работать, вам просто нужно поместить этот метод расширения в любой статический класс, и тогда вы сможете писать код, подобный приведенному выше, в любое время:
public static IEnumerable<Visual> GetChildren(this Visual parent, bool recurse = true)
{
if (parent != null)
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
// Retrieve child visual at specified index value.
var child = VisualTreeHelper.GetChild(parent, i) as Visual;
if (child != null)
{
yield return child;
if (recurse)
{
foreach (var grandChild in child.GetChildren(true))
{
yield return grandChild;
}
}
}
}
}
}
Кроме того, если вам не нравится, когда рекурсия включена по умолчанию, вы можете изменить объявление метода расширения, чтобы recurse = false
было поведением по умолчанию.