[从这里复制我的另一个问题的答案。]
真棒香肠!我想到了!
通常,当您收到Initialized
事件(或在OnInitialized
覆盖内)时,您可以访问 XAML 设置的属性值。然而,UserControl
类的工作方式略有不同,因为它们依赖于InitializeComponent
被调用来水合 UI 并设置相关的成员变量等。
问题是调用在构造函数中,最终调用OnInitialized
(并因此引发Initialized
事件),但这发生在应用 XAML 设置属性之前,这意味着您还没有访问它们的权限,我需要。
有人可能认为这对Loaded
事件很有用——根据这些属性完成初始化——但如果你在那里执行额外的初始化,你就会与你的消费者创建一个潜在的竞争条件,如果他们订阅你的Loaded
事件并在你面前得到它,然后在他们的处理程序中尝试访问你的控件,他们将访问一个未初始化的控件。
然后我发生了一些事情......正如我在上面展示的那样,如果你InitializeComponent
从构造函数中删除调用,Initialized
事件现在会按你的预期工作,但当然你的 UI 还没有水合,因为你还没有调用InitializeComponent
.
那么,如果您将该调用移到OnInitialized
覆盖的开头,在调用之前base.OnInitialized
,因此在Initialized
引发事件之前会发生什么?
是的!那行得通!:)
这样,您不仅拥有了 XAML 设置的属性,而且还可以在任何人收到Initialized
事件(更不用说Loaded
事件)之前完全加载 UI,这就是Initialized
应该使用事件的方式。
下面是修改后的代码...
public partial class TestControl : UserControl
{
protected override void OnInitialized(EventArgs e)
{
InitializeComponent();
base.OnInitialized(e);
}
public static readonly DependencyProperty TestValueProperty = DependencyProperty.Register(
"TestValue",
typeof(string),
typeof(TestControl),
new UIPropertyMetadata("Original Value"));
public string TestValue
{
get { return (string)GetValue(TestValueProperty); }
set { SetValue(TestValueProperty, value); }
}
}
- 注意:您不再需要构造函数,除非您有特殊需要在那里做其他事情。如果你这样做了,请记住在调用之后你才能通过名称访问组成控件
InitializeComponent
,但这只是意味着你必须计划在InitializeComponent
调用和调用之间移动这种基于名称的初始化,base.OnInitialize
并且一切都会正常工作。