如何以编程方式检索用于 UI 层次结构中特定元素的 DataTemplate?

Mar*_*eIV 5 c# wpf code-behind datatemplate

我们需要在代码中确定在给定特定数据类型和该元素的情况下,哪个模板将自动应用于绑定元素。

我们并不是在寻找 DataTemplateSelector,因为它用于根据自定义逻辑告诉UI 对于给定对象使用哪个模板。相反,我们询问UI对于给定的数据类型和 UI 元素将使用哪个模板。

换句话说,我们正在寻找基于窗口资源部分中定义的模板应用的任何 WPF,这些模板可以被该窗口上的控件的资源覆盖,可以通过显式设置 DataTemplate 或直接在该元素上提供 DataTemplateSelector。

另外,我们尝试了 SelectTemplate 的默认实现,但它返回 null,所以我们也不能走这条路。

测试将询问 UI 中任何位置没有定义数据模板或选择器的元素“您将如何显示该值?” 希望它会返回一个包含 TextBlock 定义的 DataTemplate,其中文本属性设置为该对象上的 ToString 方法,这是在未定义任何其他内容时默认显示的内容。

kar*_*fus 1

Thomas Levesque 未经测试的解决方案对我来说不太有效,但提供了一个很好的起点。在我们的例子中,“容器”参数并不总是在视觉树中,所以首先我们沿着逻辑树向上走,直到找到视觉对象。这与 MarqueIV 的出色建议相结合,得出了一个相当简单的解决方案。

以下代码在生产中适用于我。你的旅费可能会改变。:)

public static DataTemplate FindTemplateForType(Type dataType, DependencyObject container)
{
    var frameworkElement = container as FrameworkElement;
    if (frameworkElement != null)
    {
        var key = new DataTemplateKey(dataType);
        var template = frameworkElement.TryFindResource(key) as DataTemplate;
        if (template != null)
            return template;
    }

    if (!(container is Visual || container is Visual3D))
    {
        container = FindClosestVisualParent(container);
        return FindTemplateForType(dataType, container);
    }
    else
    {
        var parent = VisualTreeHelper.GetParent(container);
        if (parent != null)
            return FindTemplateForType(dataType, parent);
        else
            return FindTemplateForType(dataType, Application.Current.Windows[0]);
    }
}

public static DependencyObject FindClosestVisualParent(DependencyObject initial)
{
    DependencyObject current = initial;
    bool found = false;

    while (!found)
    {
        if (current is Visual || current is Visual3D)
        {
            found = true;
        }
        else
        {
            current = LogicalTreeHelper.GetParent(current);
        }
    }

    return current;
}
Run Code Online (Sandbox Code Playgroud)