2

I have an application, which uses RelayCommands in an MVVM architecture.

It seems that at some point in time the CanExecute methods no longer get properly re-evaluated. (maybe installing latest updates for VS2013 caused this?).

The code below seems as basic as it can get, I really hope somebody can help me out.

Declaration of relay command:

public RelayCommand BrowseTorrentSiteCommand { get; private set; }

Instantiation of relay command:

BrowseTorrentSiteCommand = new RelayCommand(BrowseTorrentSiteOnExecuted, BrowseTorrentSiteOnCanExecute); 

Implementation of CanExecute:

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

Implementation of SelectedTvShow property in VM:

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

Updating the selected tv show:

    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();
    }

I intentionally commented the last line where I force the RaiseCanExecuteChanged being called, I NEVER had to use that before. Obviously this solves the problem, but I use a lot of RelayCommands and all of them seem to suffer from the same problem: their CanExecute methods are no longer re-evaluated automatically.

What can be the cause that the CanExecute method no longer gets fired ?

bas
  • 13,550
  • 20
  • 69
  • 146
  • calling `RaiseCanExecuteChanged` is what you should do, and that's how it works. There is no way CanExecute can be automatically re-evaluated unless there are some standard commands supporting such feature. Another approach is using `CommandManager` – King King Nov 02 '14 at 12:07
  • @KingKing Please see my answer below. Calling `RaiseCanExecuteChanged` should **not** be necessary. Maybe I do not understand what you are trying to tell me. – bas Nov 02 '14 at 12:37

1 Answers1

1

Update

There are two implementations of the RelayCommand in MvvmLight.

  • One in using GalaSoft.MvvmLight.Command;
  • One in using GalaSoft.MvvmLight.CommandWpf;

I changed the namespace to using GalaSoft.MvvmLight.CommandWpf; and everything works as before...

In the comment of this implementation of RelayCommand the following comment gave it away:

// 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.

Anyway, problem solved... (took me long enough...)

Orginal answer

@KingKong,

Maybe I interpret your comment wrong, but this works fine in a sample App I just created to check my sanity.

    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;
    }

The UI on top of this will enable button2 when button1 is executed.

Still, this basic behavior seems not to be working in my other application...

Any help would be greatly appreciated.

bas
  • 13,550
  • 20
  • 69
  • 146
  • I don't understand what the main part (that you've found) to solve your problem here. This answer makes no sense at all. It may be meaningful to you but remember that the community need something helpful to them. You use even some custom library here. That library may have some logic to hook up and re-evaluate the `CanExecute` automatically (like `CommandManager` can do if handling the `RequerySuggested` event). – King King Nov 02 '14 at 12:53
  • @KingKing seriously, MvvmLight is "some custom library" to you?! I think it used broadly enough in the community to make answers to fix problems using this library useful enough for SO... – bas Nov 02 '14 at 13:14
  • @KingKing, PS, if you worry so much about the value of "the community", look at what you suggest next time before you add a comment. Your comment implies that this functionality simply doens't exist, while clearly you have no experience with MvvmLight... – bas Nov 02 '14 at 13:16
  • 3
    please review your question again. Is there any way for others to know what library you are using? ***My suggestion is true*** if you don't use any library. Even the tag has just MVVM. And MVVM is just a pattern, there are many ways to follow this pattern even without using any library, understand? – King King Nov 02 '14 at 13:35
  • Yes, I understand, but RelayCommand is not part of.NET. And that is part of the question. But fine, you do have a point. Next time just ask what toolkit is used instead of giving vague comments which imply something else. I'll add mvvm-light as a tag – bas Nov 02 '14 at 15:13
  • Yes the `RelayCommand` is not part of .NET but its name is very well-known, without using any library, anyone can declare their own ***simple*** version of RelayCommand. I also prefer to call my custom command class as `RelayCommand`. – King King Nov 02 '14 at 15:16
  • @KingKing, hence "Next time just ask what toolkit is used instead of giving vague comments which imply something else" – bas Nov 02 '14 at 15:46