Stephan
Stephan

Reputation: 1999

Implement INotifyPropertyChanged on ICommand

Background

In order to implement async commands in an MVVM app I went through the following tutorials by Stephen Cleary.

Problem

When reimplementing what he proposed step by step I stumbled upon the problem that the PropertyChanged event handler in the command is always null. When running Steves sample code it is not null.

In order to understand this better I started from scratch with implementing the most basic command that one could think of:

public class SimpleCommand : ICommand, INotifyPropertyChanged
{
    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        // having a break point on the following line
        throw new NotImplementedException();
    }

    public event EventHandler CanExecuteChanged;
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Note that I have a break point set on the line that throws the NotImplementedException because I just want to see whether PropertyChanged is null or not.

The viewmodel basically just creates this command and the view binds to it via a button.

public class MainViewModel : INotifyPropertyChanged
{
    public ICommand SimpleAction { get; set; }

    public MainViewModel()
    {
        SimpleAction = new SimpleCommand();
    }

    ...
}

The window just contains one button to call that command

<Window ...>
    <Window.DataContext>
        <viewModels:MainViewModel></viewModels:MainViewModel>
    </Window.DataContext>
    <Grid>
        <Button
            Command="{Binding SimpleAction}"
            Content="Click Me!"></Button>
    </Grid>
</Window>

My assumption is that when a command implements INotifyPropertyChanged then the framework listens onto the PropertyChanged event which is obviously wrong.

So how does it work in Steves examples then? There he just implements INotifyPropertyChanged on NotifyTaskCompletion or AsyncCommand and PropertyChanged is not null.

Looking at other SO posts the usual answer in general is that DataContext is not set. Still I don't see how to set this for a command.

Actual Question

How to implement INotifyPropertyChanged properly on a command (based on ICommand) in MVVM (C#)?

Upvotes: 0

Views: 2214

Answers (1)

mm8
mm8

Reputation: 169150

The command itself has no subscribers unless you bind to a property of the command itself.

That's what @Stephen Cleary does in his article. He binds to the Execution property of the AsyncCommand<TResult> class. You bind to the SimpleAction property of the MainViewModel class.

So in your sample code, the SimpleCommand object has no subscribers and that's why the event handler returns a null reference.

Upvotes: 2

Related Questions