Wpf 在可视化树中查找控件

Wpf 在可视化树中查找控件,wpf,visual-tree,Wpf,Visual Tree,我正在尝试从数据模板获取SelectedRadioButton Wpf检查员显示了可视化树: 在代码中: void menu_StatusGeneratorChanged(object sender, EventArgs e) { var status = Menu.Items.ItemContainerGenerator.Status; if (status == System.Windows.C

我正在尝试从数据模板获取SelectedRadioButton

Wpf检查员显示了可视化树:

在代码中:

    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);
                }
            }
void菜单\u status生成器已更改(对象发送方、事件参数e)
{
var status=Menu.Items.ItemContainerGenerator.status;
if(状态==System.Windows.Controls.Primitives.GeneratorStatus.ContainerGenerated)
{
var item=Menu.Items.ItemContainerGenerator.ContainerFromIndex(0);
//项目是一个ContentPresenter
var控制=Tools.FindChild(项目);
控制=工具。FindAncestor(项目);
}
}
item
是一个ContentPresenter,请参见Wpf inspector的图像,我相信从那里我必须能够访问SelectedRadioButton。变量
控件
始终为空。

我错过了什么?我使用它们。

我用来遍历可视化树的代码没有对树中的
FrameworkElement
使用
ApplyTemplate()
方法,因此无法找到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;
    }
//
///按名称查找父控件中的子控件
/// 
公共静态DependencyObject FindChild(DependencyObject父对象,字符串名称)
{
//确认父项和名称有效。
if(parent==null | | string.IsNullOrEmpty(name))返回null;
if(parent为FrameworkElement&(parent为FrameworkElement).Name==Name)返回parent;
DependencyObject结果=null;
if(parent是FrameworkElement)(parent是FrameworkElement).ApplyTemplate();
int childrenCount=visualtreeheloper.GetChildrenCount(父级);
for(int i=0;i
感谢“dev hedgehog”的评论指出这一点(我错过了)。

我不会在生产代码中使用这种方法,它必须通过“HighCore”之类的数据绑定来完成。

在WPF中像这样操作UI元素是极为罕见的。您想做什么?在该方法内设置一个断点,并使用WPF树虚拟化器在调试器到达断点的时间点查看VisualTree。完整的VisualTree可能无法完全加载,因此WPF树虚拟化器也会显示null。如果虚拟机向您展示了具体的实例,那么您可能错误地使用了FindChild。查看WPF Tree Virtualizer您可能很不走运,陷入了最糟糕的情况,即生成器在末尾,但尚未执行容器的任何度量。@HighCore我想为初始化设置一个自定义控件的属性。但是,它们是通过ItemsControl中的DataTemplate生成的,我找不到访问点。@Gerard似乎应该通过数据绑定来完成。好的,是的,这是一个很好的教程。我不知道那件事。Dr wpf调用ApplyTemplate();加载和初始化内部控件。我同意那个教程。呵呵