我刚刚完成了使用MVVM模式用WPF和C#编写的桌面应用程序。在此应用程序中,我使用了Delegate Command实现来包装在ModelView中公开的ICommands属性。问题是这些DelegateCommands阻止了我的ModelView和View在关闭 View 后被垃圾回收。因此,直到我终止整个应用程序之前,它一直保持运转状态。我对应用程序进行了分析,发现所有有关委托(delegate)命令的内容都将模型 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);
    }
}

第二: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));
        }
    }
}

第三:窗口代码落后
public MainWindow()
    {
        InitializeComponent();
        base.DataContext = new ViewModel();
    }

第四:我的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>

最佳答案

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

  • DelegateCommand包含对ViewModel的引用-其executecanExecute属性包含对ViewModel实例的方法的引用。
  • ViewModel包含对DelegateCommand的引用-PrintCommand属性。
  • 该 View 包含对ViewModel的任意数量的引用。
  • CommandManager在其DelegateCommand事件中包含对RequerySuggested的引用。

  • 最后一个引用是一个特例:CommandManager在其WeakReference事件中使用RequerySuggested,因此尽管DelegateCommand为该事件注册了事实,但仍可以对其进行垃圾回收。

    考虑到所有这些,您应该不会有问题。如果 View 被丢弃,则ViewModelDelegateCommand均不可访问。

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

    10-08 08:34