0

New to C#/MVVM and this doesn't make sense to me?

This is my implementation of a RelayCommand inheriting from ICommand:

internal class RelayCommand : ICommand
{
    private readonly Predicate<object> _canExecute;
    private readonly Action _execute;
    public event EventHandler CanExecuteChanged = (sender, e) => {};

    public RelayCommand(Action execute) : this(execute, null){ }
    public RelayCommand(Action execute, Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter) => (_canExecute == null) ? true : _canExecute(parameter);

    public void Execute(object parameter) => _execute();
}

I found out through testing that I simply can't just do this:

public RelayCommand TestCommand;

I have to do this:

public RelayCommand TestCommand { get; set; }

Otherwise declaring the command in the constructor like this:

TestCommand = new RelayCommand(TestCommandFunction);

public void TestCommandFunction(){}

won't work. Why is this the case?

Harsh Baid
  • 59
  • 8

1 Answers1

2

Binding generally doesn't work to fields. Most binding is based on the ComponentModel PropertyDescriptor model, which works on properties. This enables notifications, validation, and none of which works with fields.

So yes you need properties.

You can either initialise them in your constructor or a common pattern is using a lazy loading style syntax with a backing field and an expression bodied property

private RelayCommand _testCommand;

public RelayCommand TestCommand => _testCommand ?? (_testCommand = new RelayCommand(...));
TheGeneral
  • 79,002
  • 9
  • 103
  • 141