如何从包含 Window 的代码后面更改 UserControl 的实例?

How can I change the instance of a UserControl from the containing Window's code behind?

在下面的更复杂的实现中,我发现了一个奇怪的行为。

我有一个 window,其中包含一个 UserControlUserControl 需要一个带参数的构造函数,因此在 Window 调用 InitializeComponent().

后重新初始化

控制XAML

<UserControl x:Class="TEMP5.MyControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="33" d:DesignWidth="48">
    <Grid>
        <Button Content="Click"
                Width="40" Height="25" Margin="4"
                Click="Button_Click"/>
    </Grid>
</UserControl>

控制C#代码

public partial class MyControl : UserControl
{
    public string Foo { get; set; }

    public MyControl()
    {
        InitializeComponent();
    }

    public MyControl(string foo): this()
    {
        Foo = foo;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Console.WriteLine($"This method was invoked on: {this.GetHashCode()} with Foo value: \"{Foo}\"");
    }
}

Window XAML

<Window x:Class="TEMP5.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:TEMP5"
        mc:Ignorable="d"
        Title="MainWindow" Height="auto" Width="auto">
    <local:MyControl x:Name="myControl"/>
</Window>

Window C#代码

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Console.WriteLine($"Parameter-less constructor creates control: {myControl.GetHashCode()}");
        myControl = new MyControl("Bar");
        Console.WriteLine($"Control is now referenced: {myControl.GetHashCode()} with Foo: {myControl.Foo}");
    }
}

控制台输出

Parameter-less constructor creates control: 66824994
Control is now referenced: 5560998 with Foo: Bar

点击按钮

This method was invoked on: 66824994 with Foo value: ""

问题

为什么 UserControl 实例没有改变?控制台输出显示该字段已更新为引用“参数化”构造函数的结果,但在原始实例上调用了按钮单击。

感谢@Clemens 在上面的评论中提供的答案。总结:

建议避免 属性 通过构造函数代替允许重新分配的实现进行分配。根据以下内容考虑数据模板的建议:C# WPF content switching.

观察到的行为是由于 myControl 字段没有引用分配给 WindowContent 属性 的实例。

myControl = new MyControl("Bar"); 替换为 Content = new MyControl("Bar"); 会产生预期的行为。但是,同样,这不是推荐的方法。

也感谢@MindSwipe 的贡献。