简体   繁体   中英

Calling CommandManager.InvalidateRequerySuggested in ViewModelBase?

Initial problem:
I'm using the typical RelayCommand implementation in my MVVM Application. I realized that the CanExecute of my RelayCommand is not always called even if meaningful properties of my ViewModel have changed.

I read that we can manually call CommandManager.InvalidateRequerySuggested to raise a RequerySuggested event. This will eventually make the Command Source call the CanExecute method.

RequerySuggested is automatically raised by the CommandManager when some UI events occurs. I feel like it would be useful if it would also be raised on PropertyChanged .

My current solution:
I modified the property changed method of my ViewModelBase class like this:

protected virtual void OnPropertyChanged(string propertyName)
{
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    Application.Current.Dispatcher?.Invoke(CommandManager.InvalidateRequerySuggested);
}

Concerns:
I have not found any ViewModelBase online implemented this way and I feel like this should be a red flag.

RelayCommand is highly recommended in MVVM for it's simplicity so I find weird that I end up having to manually call the CommandManager. Why not preferring DelegateCommand then?

I know that this causes the CanExecute to be called more often, but it is already spammed every time a UI event happens anyway.

"typical" relaycommand?

If you're using MVVMLight's relaycommand then the source is:

https://github.com/lbugnion/mvvmlight/blob/master/GalaSoft.MvvmLight/GalaSoft.MvvmLight%20(PCL)/Command/RelayCommand.cs

You can call CanExecutechanged on the relaycomand.

When you add the using statement to any viewmodel, make sure you use the CommandWPF version.

InvalidateRequerySuggested is called when there is a user input event. You would therefore be raising it twice when a user inputs anything and that changes a property you raise propertychanged on. Meaning your approach is a bad idea.

It's rare to have some data comes from a model to a viewmodel on a property by property basis. Much more usual that an event is raised and the viewmodel then composes data from a viewmodel into properties. You could probably just raise canexecutechanged the once after you get a new record or a change event or however your data changes happen when they're not user input driven.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM