gpt4 book ai didi

c# - 如何在初始化期间访问 UserControl 的 XAML 设置属性?

转载 作者:太空狗 更新时间:2023-10-29 22:37:49 25 4
gpt4 key购买 nike

我们正在编写自定义 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

属性已经改变

综上所述,我可以使用什么来根据 XAML 中的用户设置属性来初始化我的控件? (注意:加载为时已晚,因为此时控件应该已经初始化。)

XAML 代码段

<local:TestControl TestValue="New Value!" />

测试控制.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(
nameof(TestValue),
typeof(string),
typeof(TestControl),
new UIPropertyMetadata("Original Value"));

public string TestValue {
get => (string)GetValue(TestValueProperty);
set => SetValue(TestValueProperty, value);
}
}

最佳答案

很棒的香肠!我想通了!

通常,当您收到 Initialized 事件(或在 OnInitialized 覆盖内)时,您可以访问 XAML 设置的属性值。但是,UserControl 类的工作方式略有不同,因为它们依赖于调用 InitializeComponent 来混合 UI 并设置相关的成员变量等。

问题是调用是在构造函数中进行的,它最终会调用 OnInitialized(并因此引发 Initialized 事件),但这发生在 XAML-已应用设置属性,这意味着您还没有访问它们的权限,而我需要这些。

人们可能认为这对 Loaded 事件来说是一个很好的用途——根据这些属性完成初始化——但是如果你在那里执行额外的初始化,你就会创建一个潜在的竞争条件与您的消费者之间的关系在于,如果他们订阅您的 Loaded 事件并在您之前获得它,然后在他们的处理程序中尝试访问您的控件,他们将访问一个未初始化的控件。

然后我想到了一些事情...正如我在上面展示的那样,如果您从构造函数中删除 InitializeComponent 调用,Initialized 事件现在将按您预期的方式工作,但是当然你的 UI 还没有水合,因为你还没有调用 InitializeComponent

如果您将该调用移动到 OnInitialized 覆盖的开头,在调用 base.OnInitialized 之前,因此在 Initialized 之前,会发生什么 事件被引发?

是的!成功了! :)

这样您不仅拥有 XAML 设置的属性,而且在任何人获得 Initialized 事件(更不用说 Loaded 事件),这就是应该如何使用 Initialized 事件。

下面是修改后的代码...

public partial class TestControl : UserControl {

protected override void OnInitialized(EventArgs e) {
InitializeComponent();
base.OnInitialized(e);
}

public static readonly DependencyProperty TestValueProperty = DependencyProperty.Register(
nameof(TestValue),
typeof(string),
typeof(TestControl),
new UIPropertyMetadata("Original Value"));

public string TestValue {
get => (string)GetValue(TestValueProperty);
set => SetValue(TestValueProperty, value);
}
}
  • 注意:您不再需要构造函数,除非您有特殊需要在那里做其他事情。如果这样做,请记住,在调用 InitializeComponent 之前,您无法通过名称访问组成控件,但这仅意味着您必须计划在 InitializeComponent< 之间移动此类基于名称的初始化 和对 base.OnInitialize 的调用,一切都会正常进行。

关于c# - 如何在初始化期间访问 UserControl 的 XAML 设置属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18583196/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com