4

I am developing a WPF application using Prism and MVVM.

One of the requirements of the application is ability to login as different user (with different permissions).

Now most of the permissions are simple allow or disallow display particular view. All of them are implemented as DelegateCommand or sometime as DelegateCommand<T>

CanExecute for those commands returns true if user has permission to display particular view. Also I have a singleton Sessionmanager that holds user information and permissions.

When user logged in I am firing an event using EventAggregator. in the base Class for all ViewModels I am subscribing to that event and using reflection loop through all public properties of VM that of type DelegateCommand and call RaiseCanExecuteChanged for that 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 non-generics DelegateCommand properties but of course does not affect DelegateCommand<T> .

My question is How to determine that property is of type DelegateCommand<T> and cast to that particular type to be able to call RasieCanExecuteChanged?

Michael D.
  • 1,249
  • 2
  • 25
  • 44

2 Answers2

7

You can check whether the property's type derives from DelegateCommandBase, and if so - cast it to 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();
    }
}
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
0

i prefer another approach, that relay on watching property changes on the viewmodel and then rise the raisecanexecutechanged only when my monitored properties change, i posted about it here:

https://stackoverflow.com/a/30394333/1716620

thanks to that you'll end up having 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 }
 );

this way you have fine control over which variable can impact on a command, without having to put lot of boilerplate code or call RaiseCanExecuteChanged when not needed

Community
  • 1
  • 1
Not Important
  • 762
  • 6
  • 22