Проблема с удалением команды CanExecute и выполняемых обработчиков из класса главного окна

#c# #wpf #command #commandbinding

#c# #wpf #команда #привязка команд

Вопрос:

В принципе, у меня есть привязка команды для самой команды, назначенной Window.Привязки команд:

 <CommandBinding Command="local:TimerViewModel.AddTimer" 
    CanExecute="local:TimerViewModel.AddTimer_CanExecute" 
    Executed="local:TimerViewModel.AddTimer_Executed" />
  

local — это пространство имен, генерируемое по умолчанию, указывающее на пространство имен приложения. Чего я пытаюсь достичь здесь, так это иметь обработку команды внутри TimerViewModel, но я продолжаю получать следующую ошибку:

CanExecute=»local:TimerViewModel.»AddTimer_CanExecute» недопустимо. ‘local:TimerViewModel.’ AddTimer_CanExecute’ не является допустимым именем метода обработчика событий. Допустимы только методы экземпляра в сгенерированном или написанном в коде классе.

TimerViewModel довольно прост, но я считаю, что мне чего-то не хватает:

 public class TimerViewModel : ViewModelBase
{
    public TimerViewModel()
    {
        _timers = new ObservableCollection<TimerModel>();
        _addTimer = new RoutedUICommand("Add Timer", "AddTimer", GetType());
    }

    private ObservableCollection<TimerModel> _timers;

    public ObservableCollection<TimerModel> Timers
    {
        get { return _timers; }
    }

    private static RoutedUICommand _addTimer;

    public static RoutedUICommand AddTimer
    {
        get { return _addTimer; }
    }

    public void AddTimer_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    public void AddTimer_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        _timers.Add(new TimerModel(TimeSpan.FromSeconds((new Random()).Next())));
    }
}
  

Кто-нибудь может указать на ошибки, которые я совершаю?

Ответ №1:

Также взгляните на RelayCommand Джоша Смита. Использование этого позволило бы вам написать вышеуказанное следующим образом:

 public class TimerViewModel : ViewModelBase {
    public TimerViewModel() {
        Timers = new ObservableCollection<TimerModel>();
        AddTimerCommand = new RelayCommand(() => AddTimer());
    }

    public ObservableCollection<TimerModel> Timers {
        get;
        private set;
    }

    public ICommand AddTimerCommand {
        get;
        private set;
    }

    private void AddTimer() {
        Timers.Add(new TimerModel(TimeSpan.FromSeconds((new Random()).Next())));
    }
}
  

Комментарии:

1. Это… Действительно приятно! Я еще не до конца понимаю, как это работает, и мне не терпится выяснить, прежде чем внедрять это, но это слишком аккуратно, чтобы не реализовывать! Спасибо!

2. Как я и предполагал, похоже, требуется некоторый дополнительный код… По-видимому, ‘new RelayCommand(AddTimer);’ не выполняет трюк, поскольку предупреждает меня, что: Аргумент 1: не удается преобразовать из ‘method group’ в ‘System. Действие<объект>’

3. Извините, я виноват. Вместо этого запишите это как () => AddTimer() ; Я обновлю приведенный выше код.

4. Разобрался, хотя для того, который я нашел, правильным использованием было бы (object x) => AddTimer (x) Тем не менее, мне удалось это сделать, но прямо сейчас я изо всех сил пытаюсь привязать его к кнопке. Command=»AddTimerCommand» было бы правильным подходом или? Потому что при этом говорится «не удается преобразовать AddTimerCommand»… РЕДАКТИРОВАТЬ: Я виноват. Следовало бы написать Command=»{Привязка AddTimerCommand}». Спасибо за вашу помощь!

Ответ №2:

Взгляните на http://www.wpftutorial.net/DelegateCommand.html для примера того, как реализовать команду делегирования для WPF. Это позволяет вам подключать Execute и CanExecute в качестве обработчиков событий. Если вы используете RoutedUICommand напрямую, вам нужно вывести из нее пользовательскую команду и переопределить Execute и CanExecute своими функциями.

Комментарии:

1. Я готов создать пользовательскую команду, но я немного запутался в том, как это сделать. Есть какие-либо советы / ссылки?