1

我正在研究Silverlight 和 WPF 中企业架构的 MVVM 生存指南,并在命令部分遇到了障碍。具体来说,它基于 Action<object> 和 Func<object, bool> 创建一个命令。在我应该“构建和运行应用程序”的时候,我却得到了编译错误。

命令内容:

public class Command : ICommand
{
  private readonly Action<object> _execute;
  private readonly Func<object, bool> _canExecute;
  public Command(Action<object> execute, Func<object, bool> canExecute)
  {
    _execute = execute;
    _canExecute = canExecute;
  }
 public void Execute(object parameter)
  {
    _execute(parameter);
  }
  public bool CanExecute(object parameter)
  {
    return (_canExecute == null) || _canExecute(parameter);
  }
  ...
}

方法调用的东西:

private Command _showDetailsCommand;
public Command ShowDetailsCommand
{
  get 
  { 
      return _showDetailsCommand 
             ?? (_showDetailsCommand 
                = new Command(ShowCustomerDetails, IsCustomerSelected));
   }
}
public void ShowCustomerDetails()
{
  if (!IsCustomerSelected()){
    throw new InvalidOperationException("Unable to display customer details. "
                + "No customer selected.");
  }
  CustomerDetailsTabViewModel customerDetailsViewModel = 
            GetCustomerDetailsTab(SelectedCustomerID);
  if (customerDetailsViewModel == null)
  {
    customerDetailsViewModel 
         = new CustomerDetailsTabViewModel
               (_dataProvider, 
                SelectedCustomerID);
    Tabs.Add(customerDetailsViewModel);
  }
  SetCurrentTab(customerDetailsViewModel);
}
private bool IsCustomerSelected()
{
  return !string.IsNullOrEmpty(SelectedCustomerID);
}

我在位下方出现波浪状的蓝线,new Command(ShowCustomerDetails, IsCustomerSelected))并带有“最佳重载匹配Northwind.Application.Command.Command(System.Action<object>, System.Func<object, bool>)具有一些无效参数”。

当我尝试编译时,我收到上述错误,以及两条消息:

Argument 1: Cannot convert from method group to System.Action<object>
Argument 2: Cannot convert from method group to System.Func<object, bool>

现在,我对 Actions 和 Funcs 的了解比昨天更多,并且几乎可以通过将命令声明更改为:

private readonly Action _execute;
private readonly Func<bool> _canExecute;

并在整个代码中做类似的事情,但后来我收到一个错误,说我没有ICommand正确实现。

为了节省我的前额/最近的墙,有人可以告诉我我做错了什么以便我可以修复它,或者给定的(书)代码让我出错,所以我可以继续前进。

4

3 回答 3

2

那是因为

private bool IsCustomerSelected()
{
    return !string.IsNullOrEmpty(SelectedCustomerID);
}

不是 typeFunc<object, bool>而是Func<bool>. 它应该看起来像

private bool IsCustomerSelected(object param)
{
    return !string.IsNullOrEmpty(SelectedCustomerID);
}

您可以使用Predicate<object>instead ,至少对我来说,更清楚的是签名应该是什么样子。

于 2013-04-24T08:26:04.617 回答
2

将您的Command课程替换为下面的代码 后,它应该是最重要的

public class Command : ICommand
{   //private readonly Action<object> _execute;
    private readonly Action _execute;

    //private readonly Func<object, bool> _canExecute;
    private readonly Func<bool> _canExecute;//instead of prev line 

    //public Command(Action<object> execute) 
    public Command(Action execute)//instead of prev line
      : this(execute, null)
    { }

    //public Command(Action<object> execute,
    public Command(Action execute,//instead of prev line 
    Func<bool> canExecute)//added instead of next line 
    //Func<object, bool> canExecute)
    {   _execute = execute;
        _canExecute = canExecute;
    }

    public void Execute(object parameter)
    {
        //_execute(parameter);
        _execute();//added instead of prev line 
    }
    public bool CanExecute(object parameter)
    {   return (_canExecute == null)
        //|| _canExecute(parameter);
        || _canExecute();//added instead of prev line 
    }
    public event EventHandler CanExecuteChanged = delegate { };
    public void RaiseCanExecuteChanged()
    {   CanExecuteChanged(this, new EventArgs());     }
}

在上述书中的代码上检查了这一点(第 205 页,第 5 章)

  • Vice R., Shujaat Siddiqi M. - Silverlight 和 WPF 中企业架构的 MVVM 生存指南,PACKT Publishing,ISBN 978-1-84968-342-5,2012

这是书本中的错误/错字

真的,在本书的随附代码中,任何人都可以从下载本书的支持文件中获得,使用正确RelayCommand的类而不是Command书中的类,据此我在上面对Command类 进行了更改

顺便说一句,这本书的在线勘误表中没有


回复@DHN 评论

改变IsCustomerSelected()方法IsCustomerSelected(object param)会带来

ShowCustomerDetails下面的片段中(它在“方法调用的东西:”之后):

private Command _showDetailsCommand;

public Command ShowDetailsCommand
{
    get
    {
        return _showDetailsCommand ??
                (_showDetailsCommand =
                    new Command
                        (
                           ShowCustomerDetails,//error
                           IsCustomerSelected
                         )
                );
    }
}

错误:

需要一个带有“void ShowCustomerDetails(object)”签名的方法

因为ShowCustomerDetails()是:

public void ShowCustomerDetails()
{
  if (!IsCustomerSelected())
     throw new InvalidOperationException("Unable to display customer details. "
     + "No customer selected.");
}

如果要更改后者,ShowCustomerDetails(object param)这会带来更多的变化和更多的必要性,以便在每次连续更改时更改代码。

只需运行代码并尝试合并您的更改,看看它会调用什么

于 2013-04-24T09:30:12.487 回答
0

Action, Func 是 C# 设计实现闭包的方式。Action 意味着你有参数对象的闭包并返回System.Void类型。Func 是用参数对象实现闭包并返回System.Bool类型的方式。

有关 C# 中闭包的更多详细信息,请参阅Jon Skeet 的闭包之美

于 2013-04-24T08:28:23.013 回答