【问题标题】:How to call RaiseCanExecuteChanged for all DelegateCommand and DelegateCommand<T> in base ViewModel Class如何在基本 ViewModel 类中为所有 DelegateCommand 和 DelegateCommand<T> 调用 RaiseCanExecuteChanged
【发布时间】:2012-03-13 07:04:43
【问题描述】:

我正在使用 Prism 和 MVVM 开发 WPF 应用程序。

应用程序的要求之一是能够以不同的用户身份登录(具有不同的权限)。

现在大多数权限都是简单的允许或禁止显示特定视图。 它们都被实现为DelegateCommand 或有时作为DelegateCommand&lt;T&gt;

如果用户有权显示特定视图,则这些命令的 CanExecute 将返回 true。 我也有一个持有用户信息和权限的单例 Sessionmanager。

当用户登录时,我正在使用 EventAggregator 触发一个事件。 在所有 ViewModel 的基类中,我订阅了该事件并使用反射 遍历 VM 类型为 DelegateCommand 的所有公共属性,并为该命令调用 RaiseCanExecuteChanged。

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

        }

这适用于所有非泛型 DelegateCommand 属性,但当然不会影响 DelegateCommand&lt;T&gt;

我的问题是如何确定该属性的类型为 DelegateCommand&lt;T&gt; 并转换为该特定类型以便能够调用 RasieCanExecuteChanged?

【问题讨论】:

    标签: c# wpf reflection mvvm delegatecommand


    【解决方案1】:

    您可以检查属性的类型是否派生自 DelegateCommandBase,如果是,请将其转换为 DelegateCommandBase 并调用 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();
        }
    }
    

    【讨论】:

    • 谢谢!我不知道可以将泛型类转换为非泛型基类。
    【解决方案2】:

    我更喜欢另一种方法,即在 viewmodel 上监视属性更改,然后仅在我监视的属性更改时才提高 raisecanexecutechanged,我在这里发布了它:

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

    多亏了你最终会得到这样的命令:

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

    通过这种方式,您可以很好地控制哪些变量会影响命令,而无需放置大量样板代码或在不需要时调用 RaiseCanExecuteChanged

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-27
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      相关资源
      最近更新 更多