2

背景

我知道从控件的构造函数中使用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 专家那里获得更详细和准确的答案(或者只是一个正确的答案,以防我完全离开这里)。

4

1 回答 1

4

因为查找资源最多涉及遍历逻辑元素树(查找与祖先关联的资源)或查看Resources当前元素的。

Parent在这两种情况下,除非或Resources已分别设置为其“正确”值,否则这是不可能的;这些是属性,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

如果在调用元素上没有找到资源,则搜索逻辑树中的父元素,然后是应用程序,然后是主题,最后是系统资源。如果资源被标记中的动态资源引用请求,则此查找方法与搜索树的方式相同。

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

此方法只是一个包装器,它获取or属性的适当类型版本(FrameworkElementFrameworkContentElement) ;因此,除非您无法确定当前类型,否则您可能需要检查相应的实例属性。FrameworkElement.ParentFrameworkContentElement.Parent

于 2013-10-14T15:14:14.470 回答