Почему мой элемент ContextMenu, привязанный к RelayCommand, всегда отключен?

Сейчас я работаю над своим первым большим приложением WPF MVVM, которое использует MVVM Light Toolkit в сочетании с RelayCommand Джоша Смита. Проблема, с которой я столкнулся, заключается в том, что я привязал эту команду к элементу в ContextMenu, который постоянно отключен.

Вот фрагмент кода MenuItem:

<MenuItem
    Header="Verwijderen"
    Command="{StaticResource DeleteNoteCommandReference}"
    CommandParameter="{Binding}" />

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

Это сама ссылка на команду:

<command:CommandReference
    x:Key="DeleteNoteCommandReference"
    Command="{Binding DeleteNoteCommand}" />

Причина, по которой я сделал это, - это проблемы с привязкой команд к ContextMenu, которые я заметил (вызванные тем фактом, что ContextMenu не является частью логического / визуального дерева). Я нашел несколько тем по этой теме в сети, и в некоторых из них я заметил класс CommandReference, который показался мне хорошим решением моей проблемы. Эти проблемы с привязкой команд действительно исчезли, но кажется, что CanExecute моей команды не распознается или что-то в этом роде, потому что MenuItem остается отключенным.

В ViewModel (который привязан к представлению как его DataContext) у меня есть следующий код для команды:

    /// <summary>
    /// Command for deleting a note.
    /// </summary>
    public RelayCommand<NoteViewModel> DeleteNoteCommand {
        get;
        private set;
    }

    /// <summary>
    /// CanExecute method for the DeleteNoteCommand.
    /// </summary>
    /// <param name="note">The NoteViewModel that CanExecute needs to check.</param>
    /// <returns>True if the note can be deleted, false otherwise.</returns>
    public bool DeleteNoteCommandCanExecute(NoteViewModel note) {
        return Notes.Contains(note);
    }

    /// <summary>
    /// Creates all commands for this ViewModel.
    /// </summary>
    private void CreateCommands() {
        DeleteNoteCommand = new RelayCommand<NoteViewModel>(param => DeleteNote(param), param => DeleteNoteCommandCanExecute(param));
    }

Что мне здесь не хватает, чтобы мой код работал? Я подумал, что это может иметь какое-то отношение к CommandReference, который я использую, но я не знаю, что искать.

Очень надеюсь, что вы, ребята, сможете помочь!


person Thomas    schedule 21.08.2011    source источник


Ответы (1)


Попробуйте установить точку останова внутри DeleteNoteCommandCanExecute и проверьте:

  1. если он вызывается перед открытием контекстного меню и
  2. код внутри DeleteNoteCommandCanExecute не вызывает исключения (например, параметр note имеет значение null)

В первом случае, если он не вызывается, попробуйте вызвать метод InvalidateRequerySuggested на CommandManager, чтобы принудительно запросить метод CanExecute.

Удачи!

person aKzenT    schedule 21.08.2011
comment
Спасибо за предложение, но точка останова вообще не вызывается ... Я читал об этом методе InvalidateRequerySuggested где-то еще, но где мне его назвать? При построении моего представления? - person Thomas; 22.08.2011
comment
Теоретически вы должны вызывать его, когда состояние меняется или может измениться. (Примечания. Содержит (примечание)). - person aKzenT; 22.08.2011
comment
Для отслеживания ошибок попробуйте поместить его в разные места (например, когда всплывает контекстное меню), чтобы посмотреть, имеет ли это значение. Но я думаю, что ваша проблема - это параметр команды, потому что вы используете привязку, но контекстное меню не является частью визуального дерева. Как ни странно, точка останова никогда не срабатывает ... - person aKzenT; 22.08.2011
comment
Хорошо, я добавил CommandManager.InvalidateRequerySuggested (); вызов кода, который добавляет объект заметки в коллекцию Notes (там, где выполняется мутация), но это не имеет никакого значения. Я также заметил, что возвращение true вместо Notes.Contains (note) в методе CanExecute тоже ничего не меняет, так что, может быть, мне нужно поискать где-нибудь еще? - person Thomas; 22.08.2011
comment
А точка останова, установленная в самом начале DeleteNoteCommandCanExecute, не попадает ни разу? - person aKzenT; 22.08.2011
comment
Еще нужно проверить, что CommandReference.Command по какой-то причине имеет значение null. CommandReference возвращает false в этом случае для CanExecute. Когда вызывается CreateCommands? От конструктора? Попробуйте установить точку останова в получателе DeleteNoteCommand - person aKzenT; 22.08.2011
comment
Ладно, похоже, я сделал очень глупый мустейк, я действительно забыл вызвать CreateCommands ;-) Большое спасибо за вашу помощь, теперь все работает нормально! - person Thomas; 22.08.2011