How to call RaiseCanExecuteChanged for all DelegateCommand and DelegateCommand <T> in the base class ViewModel
I am developing a WPF application using Prism and MVVM.
One of the requirements of the application is the ability to log in as another user (with different permissions).
Now most permissions allow you to enable or disable a specific view. All of them are implemented as DelegateCommand or once as DelegateCommand<T>
CanExecute for these commands returns true if the user has permission to display a specific view. I also have a singleton Sessionmanager that contains information about users and permissions.
When the user is logged in, I fire the event using EventAggregator. in the base class for all ViewModels I subscribe to this event and using reflection, execute all public properties of a virtual machine like DelegateCommand and call RaiseCanExecuteChanged for this command.
Type myType = this.GetType(); IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties()); foreach (PropertyInfo prop in props) { if (prop.PropertyType == typeof(DelegateCommand)) { var cmd = (DelegateCommand)prop.GetValue(this, null); cmd.RasieCanExecuteChanged(); } } This works well for all generateCommand properties not related to generics, but, of course, does not affect DelegateCommand<T> .
My question is How to determine that this property is of type DelegateCommand<T> and is discarded on this particular type in order to be able to call RasieCanExecuteChanged?
You can check if the property type is received from the DelegateCommandBase , and if so, drop it before the DelegateCommandBase and call RaiseCanExecuteChanged .
Type myType = this.GetType(); IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties()); foreach (PropertyInfo prop in props) { if (prop.PropertyType.IsSubclassOf(typeof(DelegateCommandBase))) { var cmd = (DelegateCommandBase)prop.GetValue(this, null); cmd.RaiseCanExecuteChanged(); } } I prefer a different approach, which relays when viewing property changes in view mode, and then raises raisecanexecutechanged only when the changed tracking properties change. I posted it here:
fooobar.com/questions/53503 / ...
thanks to this you will get a command like this:
this.SaveCommand = new MyDelegateCommand<MyViewModel>(this, //execute () => { Console.Write("EXECUTED"); }, //can execute () => { Console.Write("Checking Validity"); return PropertyX!=null && PropertyY!=null && PropertyY.Length < 5; }, //properties to watch (p) => new { p.PropertyX, p.PropertyY } ); Thus, you have excellent control over which variable can affect the command, without having to put a lot of template code or call RaiseCanExecuteChanged when it is not needed.