【问题标题】:Find control in the visual tree在可视化树中查找控件
【发布时间】:2013-10-31 15:13:37
【问题描述】:

我正在尝试从 DataTemplate 中获取我的 SelectedRadioButton。

Wpf Inspector 显示了可视化树:

在代码中:

    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);
                }
            }

item 是一个 ContentPresenter,看 Wpf 检查器的图像,我相信从那里我必须能够到达 SelectedRadioButton。变量control 始终为空。
我在这里想念什么?我使用这些visualtreehelpers

【问题讨论】:

  • 在 WPF 中像这样操作 UI 元素非常罕见。你想做什么?
  • 在该方法中设置断点并使用 WPF Tree Virtualizer 在调试器遇到断点的时间点查看 VisualTree。完整的 VisualTree 可能未完全加载,因此 WPF Tree Vitualizer 也会显示为空。如果 Virtualizer 向您显示具体实例,您可能使用 FindChild 错误。查看 WPF Tree Virtualizer blogs.msdn.com/b/zainnab/archive/2010/01/29/… 你可能很不幸,遇到了最坏的情况,即生成器在最后,但尚未执行容器的测量。
  • @HighCore 我想为我的一个自定义控件设置一个属性以进行初始化。但是它们是通过 ItemsControl 中的 DataTemplate 生成的,我找不到访问点。
  • @Gerard 似乎应该通过 DataBinding 来完成。
  • 好的,是的,这是一个很好的教程。我不知道那个。 wpf 博士调用 ApplyTemplate();加载并初始化其内部控件。我同意那个教程。呵呵

标签: wpf visual-tree


【解决方案1】:

我用来遍历可视化树的代码没有使用ApplyTemplate() 方法来处理树中的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;
    }

感谢“开发刺猬”的 cmets 指出这一点(我错过了)。
我不会在生产代码中使用这种方法,它必须通过像“HighCore”注释的数据绑定来完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多