如何从包含 Window 的代码后面更改 UserControl 的实例?
How can I change the instance of a UserControl from the containing Window's code behind?
在下面的更复杂的实现中,我发现了一个奇怪的行为。
我有一个 window,其中包含一个 UserControl
。 UserControl
需要一个带参数的构造函数,因此在 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
字段没有引用分配给 Window
的 Content
属性 的实例。
将 myControl = new MyControl("Bar");
替换为 Content = new MyControl("Bar");
会产生预期的行为。但是,同样,这不是推荐的方法。
也感谢@MindSwipe 的贡献。
在下面的更复杂的实现中,我发现了一个奇怪的行为。
我有一个 window,其中包含一个 UserControl
。 UserControl
需要一个带参数的构造函数,因此在 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
字段没有引用分配给 Window
的 Content
属性 的实例。
将 myControl = new MyControl("Bar");
替换为 Content = new MyControl("Bar");
会产生预期的行为。但是,同样,这不是推荐的方法。
也感谢@MindSwipe 的贡献。