[英]Specifically for a User Control, is there a place after the constructor, but before the Loaded event where you can access properties set in XAML?
[英]How can you access XAML-set properties of a UserControl during initialization?
我们正在编写自定义UserControl(而不是无形控件),我们需要根据消费者在XAML中控制的属性执行一些初始化。
现在在大多数情况下,您将使用Initialized事件(或OnInitialized覆盖),因为在触发时,已应用了所有XAML集属性,但在UserControl的情况下,情况并非如此。 触发Initialized事件时,所有属性仍处于默认值。
我没有注意到其他控件,只是UserControls,不同之处在于它们在构造函数中调用InitializeComponent(),所以作为测试,我评论说该行并运行代码,果然,这次是在Initialized期间事件的性质设定。
以下是一些代码和测试结果,证明了这一点......
在构造函数中调用InitializeComponent的结果:
(注意:值仍未设置)
TestValue (Pre-OnInitialized): Original Value
TestValue (Initialized Event): Original Value
TestValue (Post-OnInitialized): Original Value
InitializeComponent的结果已完全注释掉:
(注意:虽然已设置值,但未加载控件,因为它需要InitializeComponent)
TestValue (Pre-OnInitialized): New Value!
TestValue (Initialized Event): New Value!
TestValue (Post-OnInitialized): New Value! // Event *was* called and the property has been changed
所有这些说,我可以使用什么来初始化我的控件基于XAML中的用户设置属性? (注意:加载已经太晚了,因为到那时控件应该已经初始化了。)
XAML片段
<local:TestControl TestValue="New Value!" />
TestControl.cs
public partial class TestControl : UserControl
{
public TestControl()
{
this.Initialized += TestControl_Initialized;
InitializeComponent();
}
protected override void OnInitialized(EventArgs e)
{
Console.WriteLine("TestValue (Pre-OnInitialized): " + TestValue);
base.OnInitialized(e);
Console.WriteLine("TestValue (Post-OnInitialized): " + TestValue);
}
void TestControl_Initialized(object sender, EventArgs e)
{
Console.WriteLine("TestValue (Initialized Event): " + TestValue);
}
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); }
}
}
Awesomesausage! 我想到了!
通常,当您收到Initialized
事件(或在OnInitialized
覆盖内)时,您可以访问XAML设置的属性值。 但是, UserControl
类的工作方式略有不同,因为它们依赖于调用InitializeComponent
来水合UI并设置相关的成员变量等。
问题是调用是在构造函数中,而构造函数最终调用OnInitialized
(从而引发Initialized
事件)但是在应用XAML集属性之前发生了这种情况,这意味着您还没有访问它们,我需要的。
有人可能会认为这对Loaded
事件很有用 - 根据这些属性完成初始化 - 但是如果你在那里进行额外的初始化,那么如果他们订阅了你的消费者就会产生潜在的竞争条件Loaded
事件并在你之前得到它,然后在他们的处理程序中尝试访问你的控件,他们将访问一个未初始化的控件。
然后我发生了一些事情......正如我在上面所示,如果你从构造函数中删除了InitializeComponent
调用,那么Initialized
事件现在可以正常工作了,但是当然你的UI还没有被水合,因为你还没有调用InitializeComponent
。
那么如果在调用base.OnInitialized
之前将调用移动到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
调用之间移动这种基于名称的初始化,事情会起作用正好。 请在调用InitializeComponent之前注册初始化事件。 只要调用EndInit或OnVisualParentChanges方法(即在InitializeComponent之后),就会引发此事件。
public TestControl()
{
this.Initialized += TestControl_Initialized;
InitializeComponent();
}
谢谢
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.