【问题标题】:C# WPF Declare an ICommand in a single lineC# WPF 在一行中声明一个 ICommand
【发布时间】:2022-11-12 20:20:49
【问题描述】:

我正在学习 WPF 和 MVVM 设计模式。目前,我的 ViewModel 中用于删除客户命令的代码如下所示:

    public class vmCustomers : INotifyPropertyChanged
    {
...
        private ICommand _commandDeleteCustomer = null;
...
        public ICommand CommandDeleteCustomer
        {
            get
            {
                if (_commandDeleteCustomer == null)
                    _commandDeleteCustomer = new RelayCommand<object>(DeleteCustomerAction, DeleteCustomerPredicate);
                return _commandDeleteCustomer;
            }
        }

        private void DeleteCustomerAction(object o)
        {
            ...stuff...
        }

        private bool DeleteCustomerPredicate(object o)
        {
            ...stuff...
            return true;
        }
    }

我想将 ICommand 的声明缩减为这样的内容,以便我可以减少每个命令的编码开销:

public readonly ICommand CommandDeleteCustomer = new RelayCommand((obj) => DeleteCustomerAction(obj), (obj) => DeleteCustomerPredicate(obj));

但我得到这个错误:

A field initializer cannot reference the non-static field, method, or property vmCustomers.DeleteCustomerAction(object)

有没有一种方法可以在一行代码中声明 ICommand,这样我就可以简单地关注与业务相关的代码,而不是重复的基础设施代码。

【问题讨论】:

  • 除了初始化表达式不会编译之外,您应该声明一个只读属性public ICommand CommandDeleteCustomer { get; } 而不是字段。然后将初始化移动到构造函数:CommandDeleteCustomer = new RelayCommand(...);
  • 谢谢@Clemens - 除了我已将 CommandDeleteCustomer 声明为只读类级别变量之外,我有点明白这一点,因此:public readonly ICommand CommandDeleteCustomer;
  • 您将无法绑定到字段(又名成员变量)。它必须是公共财产。
  • @Clemens - 你是对的(已经根据经验证实)。谢谢你。

标签: c# wpf mvvm icommand


【解决方案1】:

声明一个只读的自动实现属性

public ICommand CommandDeleteCustomer { get; }

并将初始化语句移动到视图模型构造函数

public VmCustomers()
{
    CommandDeleteCustomer = new RelayCommand(...);
}

【讨论】:

    【解决方案2】:

    如果您的 RelayCommand.CanExecuteChanegd 挂钩到 CommandManager.RequerySuggested 事件,您可以删除构造函数初始化并在单行语句中将属性初始化为只读计算属性:

    // Creates a *new instance* on every Get() access
    public ICommand CommandDeleteCustomer => new RelayCommand(...);
    
    // The following is the verbose form of the previous single line property declaration:
    public ICommand CommandDeleteCustomer
    {
      get => new RelayCommand(...);
    }
    

    为确保同一个实例从属性返回,使用属性初始化器(单行语句):

    // Returns the *same instance* on every Get() access.
    // Note that you can't reference instance members like fields and properties from the initializer. 
    // This means the command delegates would have to be defined as 'private static'.
    public ICommand CommandDeleteCustomer { get; } = new RelayCommand<object>(DeleteCustomerAction, DeleteCustomerPredicate);
    
    private static void DeleteCustomerAction(object o)
    {
      ...stuff...
    }
    
    private static bool DeleteCustomerPredicate(object o)
    {
      ...stuff...
      return true;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-30
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 2020-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多