[英]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>
当您点击“打我”按钮时,标签将变为一个数字,此数字在以后的每次点击中都会递增。
由于i
仅由RelayCommand
动作使用,因此我想将声明作为局部变量移到构造器中。 但是当我这样做时,我得到一个非常奇怪的行为:该命令根本不会触发,或者触发一次然后停止。
有趣的是,如果我不使用RelayCommand
并将闭包连接到按钮的Click
事件,那么无论我在哪里定义i
,它都可以工作。 因此,这一定是RelayCommand
处理关闭的方式。
有什么猜想吗?
问题是传递给命令的闭包最终会被垃圾收集。 归功于 此Stack Overflow答案和MVVMLight文档项目 。
传递给RelayCommand
的命令action和enable函数与弱引用一起存储,因此,除非将RelayCommand
保留在其中,否则它们将在某些时候被垃圾回收。 解决方案是,如果您的操作或启用函数为闭包,则使用keepTargetAlive
构造函数参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.