Есть ли какие-либо последствия для производительности с CanExecuteCommand? - PullRequest
6 голосов
/ 07 сентября 2011

Каковы последствия для производительности при использовании CanExecuteCommand объекта ICommand.Метод выполняется снова и снова?

Мне нужно перебрать коллекцию из примерно 200 объектов, на основе которой решено, должна ли быть включена кнопка, связанная с Командой?Выполняется ли CanExecuteCommand несколько раз, что замедляет работу моего приложения

Ответы [ 2 ]

13 голосов
/ 07 сентября 2011

Интерфейс ICommand выглядит следующим образом:

public interface ICommand
{
    // two methods
    bool CanExecute(object parameter);
    void Execute(object parameter);

    // one event
    event EventHandler CanExecuteChanged;
}

Событие CanExecuteChanged должно вызываться всякий раз, когда вы хотите указать, что метод CanExecute должен быть проверен / вызван WPF. Тот, кто реализует ICommand, должен вызвать событие, а тот, кто должен обновить состояние включения кнопки в графическом интерфейсе (система WPF), должен зарегистрироваться и обработать событие, и он вызывает CanExecute.

В классе RelayCommand Джоша Смита он использует встроенный в WPF класс CommandManager для повышения CanExecuteChanged:

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

По сути, WPF CommandManager - это синглтон, который прослушивает все виды перенаправленных событий: KeyUpEvent, MouseUpEvent и т. Д., А затем сообщает всем «эй, что-то интересное произошло», вызывая событие RequerySuggested. Поэтому, если вы используете RelayCommand, ваш CanExecute будет вызываться каждый раз, когда CommandManager думает, что в GUI происходит что-то интересное (даже если это не имеет никакого отношения к вашей коллекции). Если у вас есть 50 команд, каждый раз, когда вы нажимаете клавишу, она перепроверяет все 50 команд. Так что да, это может быть проблемой производительности. Однако, если ваша логика в вашем CanExecute методе действительно проста, это, вероятно, не проблема. Вывод: не выполняйте вызовы базы данных или сетевого API в методе CanExecute.

Альтернативой откату CommandManager.RequerySuggested для поднятия события ICommand.CanExecuteChanged является свертывание собственной версии RelayCommand, где вы выполняете свою собственную проверку и поднимаете CanExecuteChanged вручную, или смотрите на каркас Prism * Класс 1032 *, где они не связаны с CommandManager, и вам нужно вручную вызвать событие CanExecuteChanged, что вы, вероятно, могли бы сделать, создав прослушиватель для PropertyChanged и затем подняв CanExecuteChanged по команде.

Я согласен с @Will выше, хотя. RelayCommand, вероятно, будет работать более 80% времени без проблем. Если вы начнете находить проблемы с производительностью, то вы можете создать свою собственную версию RelayCommand или использовать Prism DelegateCommand и повысить CanExecuteChanged вручную.

0 голосов
/ 02 ноября 2014

Для будущих гуглов: Я создал несколько другую реализацию команды. Например, он связан с событием OnPropertyChanged класса ViewModelBase, но также позволяет модели представления вызывать событие CanExecuteChanged для всех экземпляров Command внутри него, независимо от изменения свойства, например, в случае One Way К исходному сценарию привязки. Это решение является частью сборки PerrypheralFrameowrk.WPF, доступной в nuget и codeplex. Поищи это. Вики Codeplex содержит подробную документацию, также как и классы в сборке.

...