将所有属性都传递到 UserControl 后,有没有办法对其进行初始化? [复制]

Posted

技术标签:

【中文标题】将所有属性都传递到 UserControl 后,有没有办法对其进行初始化? [复制]【英文标题】:Is there a way to initialize a UserControl once all all properties have been passed into it? [duplicate] 【发布时间】:2021-12-28 22:23:48 【问题描述】:

我目前正在创建一个 WPF 应用程序,我注意到一些奇怪的事情。通过属性将数据传递到 UserControl 似乎有延迟。

    public partial class TestControl : UserControl
    
        public string Subject  get; set;  = "Foo";

        public TestControl()
        
            InitializeComponent();
            DataContext = this;
            Start();
        

        public async Task Start()
        
            Debug.WriteLine("Subject is: " + Subject);
            await Task.Delay(1);
            Debug.WriteLine("Subject is: " + Subject);
        
    

在主窗口中,我设置了 UserControl 的 Subject 属性:

<Window x:Class="TestApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestApplication"
        xmlns:views="clr-namespace:TestApplication.Views"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <views:TestControl Subject="Bar"></views:TestControl>
    </Grid>
</Window>

在输出中我打印出默认值 Foo,然后 1 毫秒后我得到 Bar。

Subject is: Foo
Subject is: Bar

有没有办法保证用传入的值而不是默认值初始化组件,而不会人为地增加一些延迟让它工作?

【问题讨论】:

您可能应该阅读Object Lifetime Events。在您的示例中,您可以在初始化事件中调用 Start 方法,但您必须小心使用该事件(请参阅链接)。如果您有复杂的初始化要求,加载的事件会更安全。此外,您应该收到一条警告,上面写着 Because this call is not awaited, execution of the current method continues before the call is completed,因为您没有等待您的 Start 方法。 请注意,只要您想绑定控件的属性,例如与Subject="Binding SubjectInViewModel" 一样,该属性必须声明为dependency property。在这种情况下,时间也会不同,因为绑定是稍后评估的。您还必须注意不要显式设置控件的 DataContext,因为这会破坏此类绑定。除此之外,使用Loaded 事件。 【参考方案1】:

没有延迟。

您正在从TestControl 的构造函数中调用Start,由于它是一个async Task 函数,它会在遇到await 时立即从该方法返回。

然后,WPF 可以继续使用其配置数据填充控件 - 从而将 Subject 设置为 Bar

与此同时,await Task.Delay(1) 完成,您现在打印 Bar 的新值。

实际上,您正在通过在对象构造期间调用即发即弃方法来创建感知的时间问题。

【讨论】:

OK... 那么如何让我的Start 方法仅在Subject 设置为Bar 时运行? @Alex - WPF 在初始化控件后会引发一个事件。把你的代码放在那里。

以上是关于将所有属性都传递到 UserControl 后,有没有办法对其进行初始化? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 MVVM 将 UserControl 从插件传递到我的主窗口?

WPF - 将 UserControl 可见性绑定到属性

如何将 WPF DataGrid DataColumns 可见性绑定到 UserControl 的 ViewModel 上的属性?

使用UserControl内部的基本控件的属性

WINFORM UserControl属性的特性

UserControl:如何转换依赖属性并绑定到结果