Commands using Action<> and Func<>

mcalex picture mcalex · Apr 24, 2013 · Viewed 10.7k times · Source

I am working through MVVM Survival Guide for Enterprise Architectures in Silverlight and WPF and have hit a snag in the Command section. Specifically, it creates a command based on an Action<object> and Func<object, bool>. At a point where I'm supposed to 'build and run the application', I am instead getting compile errors.

The command stuff:

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

The method call stuff:

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

I get wavy blue lines under the new Command(ShowCustomerDetails, IsCustomerSelected)) bit with a 'The best overloaded match for Northwind.Application.Command.Command(System.Action<object>, System.Func<object, bool>) has some invalid arguments'.

When I try to compile, I get the above error, plus two messages:

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

Now, I know a lot more about Actions and Funcs than I did yesterday, and can almost bypass the errrors by changing the command declaration to:

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

and doing similar throughout the code, but then I get an error saying I haven't implemented ICommand properly.

To save my forehead/the nearest wall, can somebody either tell me what I haven't done right so I can fix it, or that the given (book) code is leading me awry, so I can move on.

Answer

DHN picture DHN · Apr 24, 2013

Well that's because

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

is not of type Func<object, bool> but of Func<bool>. It should look like

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

You could use Predicate<object> instead , which is, at least for me, more clear, how the signature should look like.