c# - 专门针对用户控件,在构造函数之后但在 Loaded 事件之前是否有一个地方可以访问 XAML 中设置的属性?

标签 c# wpf loaded

我们有一个问题,即我们的用户控件是根据用户在使用我们的控件时在 XAML 中设置的内容进行初始化的。目前,我们正在使用“已加载”事件来根据用户设置或未设置的内容采取行动。

但是,使用 Loaded 事件的问题是此控件的另一个兄弟正在使用他们的加载事件来设置我们的东西,自从我们的 Loaded 事件尚未触发。 (如果你愿意的话,这是一个 UI 竞争条件。)

同样,我们不能将代码移至构造函数,因为 WPF 系统尚未设置控件使用者的 XAML 指定的属性。由于上述原因,我们不能使用 Loaded 事件。初始化似乎也不起作用。

我也研究过 ISupportsInitialize,但那是我们将批量设置控件属性的地方,而不是外部的东西,所以这似乎也不合适。

想法?

更新

后来我发现这是 UserControls 特有的异常现象。他们以不同的方式处理初始化。您可以在我的后续问题中找到更多详细信息...

...但是在构造函数中调用 InitializeComponent 的简短版本实际上引发了 Initialized 事件,但是在实际设置 XAML 定义的属性之前就这样做了。将其注释掉,现在当 Initialized 触发时设置属性,但当然您的控件的 UI 没有加载!实际上有点令人沮丧。

仍在寻找解决方案。可以在那里找到代码示例和更多详细信息。

最佳答案

[从我的另一个问题复制我的答案 here .]

很棒的香肠!我想通了!

通常,当您收到 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(
        "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 的调用,一切都会正常进行。

关于c# - 专门针对用户控件,在构造函数之后但在 Loaded 事件之前是否有一个地方可以访问 XAML 中设置的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18580352/

相关文章:

c# - Entity Framework 不插入记录

c# - 使用 GET 访问 WCF 休息服务时出现 400 http 错误请求错误

javascript - jQuery 无法在 Firefox 中加载

javascript - 在 Javascript 中判断视频是否加载

c# - JsonConverter 等效于 HTTP GET 参数

c# - NHibernate 插入子查询

c# - 如何检查 $(ConfigurationName) 是否包含字符串

c# - 如何在自定义 MarkupExtension 中处理 Freezable?

javascript - 单击页面加载后添加的 span 元素

c# - 从 PictureBox 中获取指定颜色的所有像素点