【问题标题】:RelayCommand canexecute never gets re-evaluatedRelayCommand canexecute 永远不会被重新评估
【发布时间】:2014-12-29 05:08:56
【问题描述】:

我有一个应用程序,它在 MVVM 架构中使用 RelayCommands。

似乎在某个时间点,CanExecute 方法不再得到正确的重新评估。 (也许安装 VS2013 的最新更新会导致这种情况?)。

下面的代码看起来很基本,我真的希望有人能帮助我。

中继命令声明:

public RelayCommand BrowseTorrentSiteCommand { get; private set; }

中继命令实例化:

BrowseTorrentSiteCommand = new RelayCommand(BrowseTorrentSiteOnExecuted, BrowseTorrentSiteOnCanExecute); 

CanExecute 的实现:

private bool BrowseTorrentSiteOnCanExecute()
{
    return _mainViewViewModel.SelectedTvShow != null;
}

在 VM 中实现 SelectedTvShow 属性:

public TvShowViewModel SelectedTvShow
{
    get { return _selectedTvShow; }
    set
    {
        _selectedTvShow = value; 
        OnPropertyChanged();
    }
}

更新选定的电视节目:

    public void TvShowsSelectionChanged()
    {
        Episodes.Clear();

        var queryEpsidesForSelection = new QueryEpsidesForSelection(TvShows);
        foreach (var episode in queryEpsidesForSelection.QueryEpisodes())
        {
            Episodes.Add(episode);
        }
        SelectedTvShow = queryEpsidesForSelection.SelectedTvShow;
        MainCommandsViewModel.DownloadNewestEpisodesCommand.RaiseCanExecuteChanged();
        //MainCommandsViewModel.BrowseTorrentSiteCommand.RaiseCanExecuteChanged();
    }

有意评论了我强制调用RaiseCanExecuteChanged 的最后一行,我以前从未使用过它。显然这解决了问题,但我使用了很多 RelayCommands,而且它们似乎都遇到了同样的问题:它们的 CanExecute 方法不再自动重新评估。

CanExecute 方法不再被触发的原因是什么?

【问题讨论】:

  • 调用RaiseCanExecuteChanged 是你应该做的,这就是它的工作原理。除非有一些标准命令支持此类功能,否则无法自动重新评估 CanExecute。另一种方法是使用CommandManager
  • @KingKing 请在下面查看我的回答。调用RaiseCanExecuteChanged 应该不需要。也许我不明白你想告诉我什么。

标签: c# wpf mvvm mvvm-light relaycommand


【解决方案1】:

更新

在 MvvmLight 中有两种RelayCommand 的实现。

  • using GalaSoft.MvvmLight.Command;中的一个
  • using GalaSoft.MvvmLight.CommandWpf;中的一个

我将命名空间更改为using GalaSoft.MvvmLight.CommandWpf;,一切正常...

RelayCommand 的这个实现的评论中,以下评论泄露了它:

// Remarks:
//     If you are using this class in WPF4.5 or above, you need to use the GalaSoft.MvvmLight.CommandWpf
//     namespace (instead of GalaSoft.MvvmLight.Command).  This will enable (or
//     restore) the CommandManager class which handles automatic enabling/disabling
//     of controls based on the CanExecute delegate.

不管怎样,问题解决了……(花了我足够长的时间……)

原始答案

@金刚,

也许我对您的评论的解释有误,但这在我刚刚创建的用于检查我的理智的示例应用中可以正常工作。

    public MainViewModel()
    {
        Command1 = new RelayCommand(OnCommand1Executed, () => true);
        Command2 = new RelayCommand(OnCommand2Executed, OnCommand2CanExecute);
    }

    private void OnCommand1Executed()
    {
        _command2CanExecute = true;
    }

    private void OnCommand2Executed()
    {
        // Not implemented
    }

    private bool OnCommand2CanExecute()
    {
        return _command2CanExecute;
    }

在此之上的 UI 将在 button1 执行时启用 button2。

不过,这种基本行为似乎不适用于我的其他应用程序...

任何帮助将不胜感激。

【讨论】:

  • 我不明白在这里解决您的问题的主要部分(您已经找到)。这个答案根本没有意义。这对您可能很有意义,但请记住,社区需要对他们有帮助的东西。您甚至可以在这里使用一些自定义库。该库可能有一些逻辑来自动连接和重新评估CanExecute(就像CommandManager在处理RequerySuggested事件时可以做的那样)。
  • @KingKing 说真的,MvvmLight 对你来说是“一些自定义库”?!我认为它在社区中使用得足够广泛,可以使用这个库为解决问题提供足够有用的答案...
  • @KingKing,PS,如果你这么担心“社区”的价值,下次在添加评论之前看看你的建议。您的评论暗示此功能根本不存在,而显然您对 MvvmLight 没有经验...
  • 请再次检查您的问题。有没有办法让其他人知道你正在使用什么库? 如果您不使用任何库,我的建议是正确的。甚至标签也只有 MVVM。而 MVVM 只是一种模式,即使不使用任何库,也有很多方法可以遵循这种模式,明白吗?
  • 是的,我明白,但 RelayCommand 不是 .NET 的一部分。这是问题的一部分。不过没关系,你说得有道理。下次只需询问使用了什么工具包,而不是给出暗示其他东西的模糊 cmets。我将 mvvm-light 添加为标签
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 2013-02-10
  • 2020-05-27
相关资源
最近更新 更多