Утечка памяти в приложении WPF из-за DelegateCommand

Я только что закончил настольные приложения, записанные в 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>

9
задан Abdullah BaMusa 15 June 2010 в 01:07
поделиться

1 ответ

Что в вашем случае содержит ссылку на что?

  1. DelegateCommand содержит ссылку на ViewModel - его свойства execute и canExecute содержат ссылки на методы экземпляра ViewModel .

  2. ViewModel содержит ссылку на DelegateCommand - его свойство PrintCommand .

  3. Представление содержит любое количество ссылок на ViewModel .

  4. CommandManager содержит ссылку на DelegateCommand в своем событии RequerySuggested .

Последняя ссылка является частным случаем: CommandManager использует WeakReference в своем событии RequerySuggested , поэтому, несмотря на то, что DelegateCommand регистрируется для этого события, его все еще можно удалить сборщиком мусора.

Учитывая все это, у вас не должно быть проблем. Если представление будет удалено, ни ViewModel , ни DelegateCommand не будут доступны.

Вы говорите, что профилировали приложение, и DelegateCommand содержит ссылку на ViewModel . Мне кажется, что следующим логическим вопросом должен быть: что содержит ссылку на DelegateCommand ? Это не должно быть CommandManager . Есть ли в вашем приложении что-то еще, что ссылается на ваши команды?

9
ответ дан 3 November 2019 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: