不一致的行为:带有闭包捕获局部变量的 MVVM RelayCommandWPF
Inconsistent behavior: MVVM RelayCommandWPF with closure capturing local variable
我试图理解我在 MVVM RelayCommand 中看到的一些奇怪行为,它的行为是捕获局部变量的闭包。
最小可行代码示例:
using GalaSoft.MvvmLight.CommandWpf;
namespace WpfApplication3
{
public partial class MainWindow
{
public RelayCommand DoIt { get; }
int i = 0;
public MainWindow()
{
DoIt = new RelayCommand( () =>
{
System.Console.WriteLine( "doing it!" );
button.Content = (++i).ToString();
} );
InitializeComponent();
}
}
}
XAML:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight">
<Button x:Name="button" Content="Hit me" Command="{Binding DoIt, RelativeSource={RelativeSource AncestorType=Window}}"/>
</Window>
当您点击 "Hit me" 按钮时,标签会变为一个数字,该数字会随着每次后续点击而递增。
由于 i
仅由 RelayCommand
操作使用,我想将声明作为局部变量移动到构造函数中。但是当我这样做时,我会得到非常奇怪的行为:该命令根本不会触发,或者触发一次然后停止。
有趣的是,如果我取消 RelayCommand
并将闭包连接到按钮的 Click
事件,那么无论我在何处定义 i
,它都有效。所以这一定是 RelayCommand
处理闭包的方式。
有什么猜测吗?
问题是传递给命令的闭包最终得到 garbage-collected。感谢 this Stack Overflow answer and this MVVMLight documentation item。
您传递给 RelayCommand
的命令操作和启用函数存储在弱引用中,因此除非 RelayCommand
之外的其他内容保留在它们上面,否则它们有时会 garbage-collected观点。如果您的操作或启用函数是闭包,解决方案是使用 keepTargetAlive
构造函数参数。
我试图理解我在 MVVM RelayCommand 中看到的一些奇怪行为,它的行为是捕获局部变量的闭包。
最小可行代码示例:
using GalaSoft.MvvmLight.CommandWpf;
namespace WpfApplication3
{
public partial class MainWindow
{
public RelayCommand DoIt { get; }
int i = 0;
public MainWindow()
{
DoIt = new RelayCommand( () =>
{
System.Console.WriteLine( "doing it!" );
button.Content = (++i).ToString();
} );
InitializeComponent();
}
}
}
XAML:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight">
<Button x:Name="button" Content="Hit me" Command="{Binding DoIt, RelativeSource={RelativeSource AncestorType=Window}}"/>
</Window>
当您点击 "Hit me" 按钮时,标签会变为一个数字,该数字会随着每次后续点击而递增。
由于 i
仅由 RelayCommand
操作使用,我想将声明作为局部变量移动到构造函数中。但是当我这样做时,我会得到非常奇怪的行为:该命令根本不会触发,或者触发一次然后停止。
有趣的是,如果我取消 RelayCommand
并将闭包连接到按钮的 Click
事件,那么无论我在何处定义 i
,它都有效。所以这一定是 RelayCommand
处理闭包的方式。
有什么猜测吗?
问题是传递给命令的闭包最终得到 garbage-collected。感谢 this Stack Overflow answer and this MVVMLight documentation item。
您传递给 RelayCommand
的命令操作和启用函数存储在弱引用中,因此除非 RelayCommand
之外的其他内容保留在它们上面,否则它们有时会 garbage-collected观点。如果您的操作或启用函数是闭包,解决方案是使用 keepTargetAlive
构造函数参数。