我刚刚完成了使用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
的引用-其execute
和canExecute
属性包含对ViewModel
实例的方法的引用。 ViewModel
包含对DelegateCommand
的引用-PrintCommand
属性。 ViewModel
的任意数量的引用。 CommandManager
在其DelegateCommand
事件中包含对RequerySuggested
的引用。 最后一个引用是一个特例:
CommandManager
在其WeakReference
事件中使用RequerySuggested
,因此尽管DelegateCommand
为该事件注册了事实,但仍可以对其进行垃圾回收。考虑到所有这些,您应该不会有问题。如果 View 被丢弃,则
ViewModel
和DelegateCommand
均不可访问。您说您已经分析了该应用程序,并且
DelegateCommand
持有对ViewModel
的引用。在我看来,下一个逻辑上的问题应该是:对DelegateCommand
的引用是什么?它不应该是CommandManager
。您的应用程序中是否还有其他引用命令的内容?