Я только что закончил настольные приложения, записанные в WPF и c# с помощью шаблона MVVM. В этом приложении я использовал реализацию Команды Делегата для обертывания свойств ICommands, выставленных в мой ModelView. Проблемой являются эти DelegateCommands, препятствуют тому, чтобы мой ModelView и Представление были собраны "мусор" после закрытия представления. Таким образом, это остается забавляющимся, пока я не завершаю целое приложение. Я представляю приложение, я нахожу, что это - все о delegatecommand что, сохраняя modelview в памяти. Как я мог избежать этой ситуации и являюсь этим по своей природе 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();
}
Forth: мой 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
регистрируется для этого события, его все еще можно удалить сборщиком мусора.
Учитывая все это, у вас не должно быть проблем. Если представление будет удалено, ни ViewModel
, ни DelegateCommand
не будут доступны.
Вы говорите, что профилировали приложение, и DelegateCommand
содержит ссылку на ViewModel
. Мне кажется, что следующим логическим вопросом должен быть: что содержит ссылку на DelegateCommand
? Это не должно быть CommandManager
. Есть ли в вашем приложении что-то еще, что ссылается на ваши команды?