wpf 在可视化树中查找控件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19523139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find control in the visual tree
提问by Gerard
I am trying to get my SelectedRadioButton from a DataTemplate.
我正在尝试从 DataTemplate 中获取我的 SelectedRadioButton。
Wpf Inspector showed the Visual Tree:
Wpf Inspector 显示了可视化树:


and in code:
并在代码中:
void menu_StatusGeneratorChanged(object sender, EventArgs e)
{
var status = Menu.Items.ItemContainerGenerator.Status;
if (status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
{
var item = Menu.Items.ItemContainerGenerator.ContainerFromIndex(0);
// item is a ContentPresenter
var control = Tools.FindChild<SelectedRadioButton>(item);
control = Tools.FindAncestor<SelectedRadioButton>(item);
}
}
itemis a ContentPresenter, see the image of Wpf inspector, I believe from there I must be able to get to the SelectedRadioButton. The variable controlis always null.
What am I missing here? I use these visualtreehelpers.
item是一个 ContentPresenter,看到 Wpf 检查器的图像,我相信从那里我必须能够到达 SelectedRadioButton。变量control始终为空。
我在这里缺少什么?我使用这些visualtreehelpers。
回答by Gerard
The code that I used to traverse the Visual Tree did not use the ApplyTemplate()method for a FrameworkElementin the tree and therefore cildren could not be found. In my situation the following code works:
我用来遍历可视化树的代码没有使用树中ApplyTemplate()的 a 方法FrameworkElement,因此找不到 cildren。在我的情况下,以下代码有效:
/// <summary>
/// Looks for a child control within a parent by name
/// </summary>
public static DependencyObject FindChild(DependencyObject parent, string name)
{
// confirm parent and name are valid.
if (parent == null || string.IsNullOrEmpty(name)) return null;
if (parent is FrameworkElement && (parent as FrameworkElement).Name == name) return parent;
DependencyObject result = null;
if (parent is FrameworkElement) (parent as FrameworkElement).ApplyTemplate();
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
result = FindChild(child, name);
if (result != null) break;
}
return result;
}
/// <summary>
/// Looks for a child control within a parent by type
/// </summary>
public static T FindChild<T>(DependencyObject parent)
where T : DependencyObject
{
// confirm parent is valid.
if (parent == null) return null;
if (parent is T) return parent as T;
DependencyObject foundChild = null;
if (parent is FrameworkElement) (parent as FrameworkElement).ApplyTemplate();
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
foundChild = FindChild<T>(child);
if (foundChild != null) break;
}
return foundChild as T;
}
Thanks for the comments of "dev hedgehog" for pointing that out (I missed it).
I will not use this approach in production code, it has to be done with databinding like "HighCore" commented.
感谢“开发刺猬”的评论指出这一点(我错过了)。
我不会在生产代码中使用这种方法,它必须通过像“HighCore”注释的数据绑定来完成。

