【问题标题】:Why is my ContextMenu item bound to a RelayCommand is always disabled?为什么我的 ContextMenu 项绑定到 RelayCommand 总是被禁用?
【发布时间】:2011-08-21 19:43:33
【问题描述】:

我现在正在开发我的第一个大型 WPF MVVM 应用程序,它使用 MVVM Light Toolkit 和 Josh Smith 的 RelayCommand。 我遇到的问题是我将此命令绑定到 ContextMenu 中的一个项目,该项目一直处于禁用状态。

这里是 MenuItem 的代码 sn-p:

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

现在我对命令绑定所做的工作如下:我使用了一个名为 CommandReference 的类,我找到了 here

这是命令引用本身:

<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 有关,但我不知道要查找什么。

真的希望你们能帮忙!

【问题讨论】:

    标签: c# wpf mvvm relaycommand canexecute


    【解决方案1】:

    尝试在DeleteNoteCommandCanExecute 内设置断点并检查:

    1. 如果在打开上下文菜单之前调用它并且
    2. DeleteNoteCommandCanExecute 内的代码不会引发异常(例如,note 参数为空)

    在第一种情况下,如果它没有被调用,请尝试在CommandManager 上调用InvalidateRequerySuggested 方法以强制重新查询CanExecute 方法。

    祝你好运!

    【讨论】:

    • 感谢您的建议,但根本没有调用断点...我在其他地方读到过这个 InvalidateRequerySuggested 方法,但我应该在哪里调用它?在构建我的视图时?
    • 理论上你应该在条件改变或可能改变时调用它。 (Notes.Contains(note))。
    • 对于 Bug 跟踪,尝试将其放在不同的地方(例如,当上下文菜单弹出时),看看它是否有所作为。但我认为你的问题是命令参数,因为你正在使用绑定,但上下文菜单不是可视树的一部分。奇怪的是断点永远不会被击中......
    • 好的,我添加了 CommandManager.InvalidateRequerySuggested();调用将注释对象添加到 Notes 集合的代码(这是完成突变的地方),但它没有任何区别。我也注意到在 CanExecute 方法中返回 true 而不是 Notes.Contains(note) 也不会改变任何东西,所以也许我必须看看其他地方?
    • 你在 DeleteNoteCommandCanExecute 最开始设置的断点甚至没有被命中一次?
    猜你喜欢
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多