I'm in the process of learning WPF and the MVVM design pattern. Currently the code in my ViewModel for a delete customer command looks like this:
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;
}
}
I'd like to slim down the declaration of the ICommand to something like this so that I can reduce the coding overhead for each command:
public readonly ICommand CommandDeleteCustomer = new RelayCommand((obj) => DeleteCustomerAction(obj), (obj) => DeleteCustomerPredicate(obj));
But I get this error:
A field initializer cannot reference the non-static field, method, or property vmCustomers.DeleteCustomerAction(object)
Is there a way I can declare the ICommand in a single line of code so that I can simply focus on business-related code rather than repeated infrastructure code.
In case your RelayCommand.CanExecuteChanegd
hooks onto the CommandManager.RequerySuggested
event you can drop the constructor initialization and initialize the property as read-only computed property in a single line statement:
// 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(...);
}
To ensure that the same instance is returned from the property, use
a) the null coalescing assignment operator (C# 8.0)
// Backing field required
private ICommand commandDeleteCustomer;
public ICommand CommandDeleteCustomer => this.commandDeleteCustomer ??= new RelayCommand(...);
// The following is the verbose form of the previous property declaration
// and uses the null coalescing operator:
public ICommand CommandDeleteCustomer => this.commandDeleteCustomer = this.commandDeleteCustomer ?? new RelayCommand(...);
b) a property initializer (single line statement):
// 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;
}