J'ai combiné le format de modèle utilisé par John Myczek et l'algorithme de Tri Q ci-dessus pour créer un algorithme findChild qui peut être utilisé sur n'importe quel parent. Gardez à l'esprit que la recherche récursive d'un arbre vers le bas peut être un processus long. J'ai seulement vérifié cela sur une application WPF, merci de commenter toute erreur que vous pourriez trouver et je corrigerai mon code.
WPF Snoop est un outil utile pour examiner l'arbre visuel - je vous recommande vivement de l'utiliser lors des tests ou de l'utilisation de cet algorithme pour vérifier votre travail.
Il y a une petite erreur dans l'algorithme de Tri Q. Après que l'enfant soit trouvé, si childrenCount est > 1 et que nous itérons à nouveau, nous pouvons écraser l'enfant correctement trouvé. C'est pourquoi j'ai ajouté un if (foundChild != null) break;
dans mon code pour gérer cette condition.
/// <summary>
/// Finds a Child of a given item in the visual tree.
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter.
/// If not matching item can be found,
/// a null parent is being returned.</returns>
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
Appelez ça comme ça :
TextBox foundTextBox =
UIHelper.FindChild<TextBox>(Application.Current.MainWindow, "myTextBoxName");
Note Application.Current.MainWindow
peut être n'importe quelle fenêtre parent.