C# 初始化期间如何访问UserControl的XAML集属性?
我们正在编写一个自定义用户控件(与无外观控件相反),并且需要根据使用者在XAML中对控件设置的属性执行一些初始化 现在,在大多数情况下,您都会使用初始化事件(或OnInitialized重写),因为在触发时,所有XAML集合属性都已应用,但对于UserControl,情况并非如此。当初始化事件激发时,所有属性仍处于其默认值 对于其他控件,我没有注意到这一点,只是UserControls,它们的不同之处在于它们在构造函数中调用InitializeComponent(),因此作为一个测试,我对该行进行了注释并运行了代码,果然,这次在初始化事件中,设置了属性 下面是一些代码和测试结果,演示了这一点 构造函数中调用InitializeComponent的结果:C# 初始化期间如何访问UserControl的XAML集属性?,c#,wpf,user-controls,initialization,C#,Wpf,User Controls,Initialization,我们正在编写一个自定义用户控件(与无外观控件相反),并且需要根据使用者在XAML中对控件设置的属性执行一些初始化 现在,在大多数情况下,您都会使用初始化事件(或OnInitialized重写),因为在触发时,所有XAML集合属性都已应用,但对于UserControl,情况并非如此。当初始化事件激发时,所有属性仍处于其默认值 对于其他控件,我没有注意到这一点,只是UserControls,它们的不同之处在于它们在构造函数中调用InitializeComponent(),因此作为一个测试,我对该行进
(注意:尚未设置值) InitializeComponent被完全注释掉的结果:
(注意:虽然已设置值,但由于控件需要InitializeComponent,因此未加载该控件) 综上所述,基于XAML中的用户集属性,我可以使用什么来初始化我的控件?(注意:加载太晚,因为此时控件应该已经初始化。) XAML片段
<local:TestControl TestValue="New Value!" />
请在调用InitializeComponent之前注册初始化事件。每当调用EndInit或OnVisualParentChanges方法时,即在InitializeComponent之后,都会引发此事件
public TestControl()
{
this.Initialized += TestControl_Initialized;
InitializeComponent();
}
谢谢太棒了!我知道了 通常,当您收到
Initialized
事件(或在OnInitialized
覆盖内)时,您可以访问XAML set属性值。但是,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之间移动基于名称的初始化。只需初始化
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); }
}
}
public TestControl()
{
this.Initialized += TestControl_Initialized;
InitializeComponent();
}
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); }
}
}