¿Cómo obtener hijos de un contenedor WPF por tipo?

¿Cómo puedo obtener los controles secundarios de tipo ComboBox en MyContainer Grid en WPF?

   

Esta línea me da un error:

 var myCombobox = this.MyContainer.Children.GetType(ComboBox); 

Este método de extensión buscará recursivamente elementos secundarios del tipo deseado:

 public static T GetChildOfType(this DependencyObject depObj) where T : DependencyObject { if (depObj == null) return null; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) { var child = VisualTreeHelper.GetChild(depObj, i); var result = (child as T) ?? GetChildOfType(child); if (result != null) return result; } return null; } 

Así que usando eso puedes pedir MyContainer.GetChildOfType() .

Children es una colección de UIElements. Por lo tanto, necesita repetir los elementos y determinar para cada elemento si es del tipo requerido. Afortunadamente, ya existe un método Linq para esto, concretamente, Enumerable.OfType , que puede llamar cómodamente utilizando la syntax del Método de extensión :

 var comboBoxes = this.MyContainer.Children.OfType(); 

Este método filtra la colección en función de su tipo y devuelve, en su caso, solo los elementos del tipo ComboBox .

Si solo desea el primer ComboBox (como su nombre de variable podría sugerir), puede agregar una llamada a FirstOrDefault() a la consulta:

 var myComboBox = this.MyContainer.Children.OfType().FirstOrDefault(); 

Busque el primer hijo de un tipo determinado que incluya un punto predeterminado (de Pantalla):

(param ‘point’ es el resultado de llamar a la función ‘PointToScreen’ (declarada en tipo Visual))

 private TDescendantType FindDescendant(DependencyObject parent, Point screenPoint) where TDescendantType : DependencyObject { int count = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(parent, i); if (child is Visual) { Point point = ((Visual)child).PointFromScreen(screenPoint); Rect rect = VisualTreeHelper.GetDescendantBounds((Visual)child); if (!rect.Contains(point)) continue; } if (child is TDescendantType) { return (TDescendantType)child; } child = FindDescendant(child, screenPoint); if (child != null) { return (TDescendantType)child; } } return null; } 

Todas estas respuestas son muy buenas, pero, si estás tratando de encontrar un niño visual específico de tipo T, o estás atrapado en obtenerlas todas y luego encuentras la que quieres, o esperando que la primera que obtienes sea la uno que quieras Combiné algunos enfoques para encontrar uno específico basado en un criterio. Es un poco como LINQ, pero no quería tratar con un enumerador recursivo.

Úselo así:

 MyContainer.FirstOrDefaultChild 

Lo escribí como un método de extensión.

 public static class DependencyObjectExtensions { public static T FirstOrDefaultChild(this DependencyObject parent, Func selector) where T : DependencyObject { T foundChild; return FirstOrDefaultVisualChildWhere(parent, selector, out foundChild) ? foundChild : default(T); } private static bool FirstOrDefaultVisualChildWhere(DependencyObject parent, Func selector, out T foundChild) where T : DependencyObject { var count = VisualTreeHelper.GetChildrenCount(parent); for (var i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(parent, i); var tChild = child as T; if (tChild != null) { if (!selector(tChild)) continue; foundChild = tChild; return true; } if (FirstOrDefaultVisualChildWhere(child, selector, out foundChild)) { return true; } } foundChild = default(T); return false; }