c# - 为什么无法在控件的构造函数中获取资源

标签 c# wpf

背景

我知道使用 FindResource 获取资源当从控件的构造函数完成时,该方法将不起作用,因为它将始终返回 null。

public class MyButton : Button
{
    public MyButton()
    {
        Style = FindResource("myStyle") as Style;
    }
}

我知道可以通过 OnApplyTemplate 来完成方法。

public override void OnApplyTemplate()
{
    Style = FindResource("myStyle") as Style;
    base.OnApplyTemplate();
}

问题

为什么?我认为这与VisualTree的加载有关。但我希望从 WPF 专家那里得到更详细、更准确的答案(或者只是一个正确的答案,以防我完全不在这儿)。

最佳答案

因为查找资源最需要遍历逻辑元素树(以查找与祖先关联的资源)或查看当前元素的Resources

在这两种情况下,这是不可能的,除非 ParentResources分别已被设置为其“正确”值;这些是属性,XAML 序列化引擎在构造函数运行后设置它们。也就是说,当你写

<Button Height="80" Width="150" />

XAML 反序列化器最终会执行相当于

var button = new Button(); // element is instantiated
button.Height = 80;        // ...and THEN properties are set
button.Width = 150;

因此,您无法在构造函数内执行任何取决于所设置的属性的操作。

为了证实上述内容,来自 FindResource 的文档:

If the resource is not found on the calling element, the parent element in the logical tree is searched next, then the application, then themes, and finally system resources. This lookup methodology is identical to how the tree is searched if a resource were requested by a dynamic resource reference in markup.

遍历逻辑树当然是通过Parent属性完成的;这是直观的,但在 LogicalTreeHelper.GetParent 的文档中也清楚地说明了这一点:

This method is merely a wrapper that gets the appropriate type version (FrameworkElement or FrameworkContentElement) of the FrameworkElement.Parent or FrameworkContentElement.Parent property; so unless you are unable to determine the current type, you might want to check the respective instance properties instead.

关于c# - 为什么无法在控件的构造函数中获取资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19363082/

相关文章:

c# - 实现 IEnumerable<T> 和 IEnumerable.GetEnumerator() 不能公开,为什么?

c# - 有人可以帮我将多个字符串数组分配给一个二维字符串数组吗?

c# - 如何没有/一个窗口标题并为任务栏设置不同的标题?

c# - 如何从 Icommand 命令添加新的 ObservableCollection?

c# - 在 ContentPresenter 子控件中设置属性

WPF 绑定(bind) Width 到 Parent.Width*0.3

c# - API 速率限制器

c# - 普通 C# 和 Orleans 中的方法调用之间的区别

c# - 在 ASP.NET 自定义控件中呈现多个控件集合

c# - 如何覆盖 MeasureOverride 以查找 ItemsControl 的大小