为什么无法在控件的构造函数中获取资源
本文关键字:构造函数 获取 资源 控件 为什么 | 更新日期: 2023-09-27 18:35:13
Background
我知道使用 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();
}
问题
为什么?我认为这与可视化树的加载有关,但我希望从你们 WPF 专家那里得到一个更详细和准确的答案(或者只是一个正确的答案,以防我完全不在这里)。
因为查找资源最需要遍历逻辑元素树(查找与祖先关联的资源)或查看当前元素的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
文档中也有明确说明:
此方法只是一个获取适当类型版本的包装器 (
FrameworkElement
或FrameworkContentElement
) 的FrameworkElement.Parent
或FrameworkContentElement.Parent
财产;所以 除非无法确定当前类型,否则可能需要 请改为检查相应的实例属性。