繁体   English   中英

不一致的行为:带有闭包的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>

当您点击“打我”按钮时,标签将变为一个数字,此数字在以后的每次点击中都会递增。

由于i仅由RelayCommand动作使用,因此我想将声明作为局部变量移到构造器中。 但是当我这样做时,我得到一个非常奇怪的行为:该命令根本不会触发,或者触发一次然后停止。

有趣的是,如果我不使用RelayCommand并将闭包连接到按钮的Click事件,那么无论我在哪里定义i ,它都可以工作。 因此,这一定是RelayCommand处理关闭的方式。

有什么猜想吗?

问题是传递给命令的闭包最终会被垃圾收集。 归功于 此Stack Overflow答案MVVMLight文档项目

传递给RelayCommand的命令action和enable函数与弱引用一起存储,因此,除非将RelayCommand保留在其中,否则它们将在某些时候被垃圾回收。 解决方案是,如果您的操作或启用函数为闭包,则使用keepTargetAlive构造函数参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM