由于DelegateCommand导致WPF应用程序中的内存泄漏

Abd*_*usa 9 c# wpf mvvm delegatecommand

我刚刚使用MVVM模式完成了用WPF和c#编写的桌面应用程序.在这个应用程序中,我使用Delegate Command实现来包装我的ModelView中公开的ICommands属性.问题是这些DelegateCommands阻止我的ModelView和View在关闭视图后被垃圾收集.因此,在我终止整个应用程序之前,它一直保持冷静.我分析了应用程序,我发现它是关于将模型视图保存在内存中的委托命令.我怎么能避免这种情况,这是mvvm模式的本质,还是我的模式的植入?谢谢.

编辑:这是我实现MVVM模式的小但完整的部分

第一:CommandDelegte类

class DelegateCommand:ICommand
{
    private Action<object> execute;
    private Predicate<object> canExcute;
    public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }
        this.execute = execute;
        this.canExcute = canExecute;
    }
    public bool CanExecute(object parameter)
    {
        if (this.canExcute != null)
        {
            return canExcute(parameter);
        }
        return true;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }


    public void Execute(object parameter)
    {
        this.execute(parameter);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二:ModelView类

public class ViewModel:DependencyObject, INotifyPropertyChanged
{
    private DelegateCommand printCommand;

    public ICommand PrintCommand
    {
        get
        {
            if (printCommand == null)
            {
                printCommand = new DelegateCommand(Print, CanExecutePrint);
            }
            return printCommand;
        }
    }
    void Print(object obj)
    {
        Console.WriteLine("Print Command");

    }
    bool CanExecutePrint(object obj)
    {
        return true;
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void OnProeprtyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

第三:窗口代码背后

public MainWindow()
    {
        InitializeComponent();
        base.DataContext = new ViewModel();
    }
Run Code Online (Sandbox Code Playgroud)

第四:我的XAML

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.InputBindings>
    <KeyBinding Key="P" Modifiers="Control" Command="{Binding Path=PrintCommand}"/>
</Window.InputBindings>
<StackPanel>
    <Button Content="Print - Ctrl+P" Width="75" Height="75" Command="{Binding Path=PrintCommand}"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

Rob*_*ney 9

在你的情况下,什么包含对什么的引用?

  1. DelegateCommand包含一个参考ViewModel-它executecanExecute属性包含到的方法的引用ViewModel实例.

  2. ViewModel包含DelegateCommand对其PrintCommand属性的引用.

  3. 该视图包含任意数量的引用ViewModel.

  4. 其中CommandManager包含DelegateCommand对其RequerySuggested事件的引用.

最后一个引用是一个特殊情况: 在其事件中CommandManager使用a ,因此尽管事件是为该事件注册的,但它仍然可以被垃圾收集.WeakReferenceRequerySuggestedDelegateCommand

鉴于这一切,你不应该有问题.如果视图被丢弃,那么ViewModel也不DelegateCommand应该可以访问.

你说你已经分析了应用程序并且DelegateCommand正在引用它ViewModel.在我看来,合乎逻辑的下一个问题应该是:什么是引用DelegateCommand?它不应该CommandManager.您的应用程序中是否还有其他引用命令的内容?