DelegateCommand<T> CanExecute When Parameter is null

Dec 12, 2012 at 2:10 PM

Hi Tony,

There appears to be an issue with the DelegateCommand<T>'s CanExecute method when the Command Parameter is null, causing it not to correctly return.  For example, this (totally contrived for illustration purposes) code works as expected (the button enables/disables in sync with the checkbox)...

<StackPanel>    
    <Button Margin="3" Grid.Row="0" Content="Test Command" Command="{Binding Path=TestCommand}" CommandParameter="Hello World" />
    <CheckBox Content="IsEnabled" IsChecked="{Binding Path=IsEnabled, Mode=TwoWay}" />
</StackPanel>

private DelegateCommand<string> _testCommand;
public DelegateCommand<string> TestCommand
{
    get
    {
        return _testCommand ?? (_testCommand = new DelegateCommand<string>(theString => { Console.WriteLine(theString); }, num => IsEnabled));
    }
}

private bool _isEnabled;
public bool IsEnabled
{
    get { return _isEnabled; }
    set
    {
        _isEnabled = value;
        NotifyPropertyChanged(prop => prop.IsEnabled);
        TestCommand.RaiseCanExecuteChanged();
    }
}

Leaving the ViewModel code exactly the same and making a couple different changes to the CommandParameter in the button.

This also works...

<StackPanel>
    <Button Margin="3" Grid.Row="0" Content="Test Command" Command="{Binding Path=TestCommand}" CommandParameter="{x:Static String.Empty}" />
    <CheckBox Content="IsEnabled" IsChecked="{Binding Path=IsEnabled, Mode=TwoWay}" />
</StackPanel>

This however, does not work (the button's enabled property will never change)...

<StackPanel>
    <Button Margin="3" Grid.Row="0" Content="Test Command" Command="{Binding Path=TestCommand}" CommandParameter="{x:Null}" />
    <CheckBox Content="IsEnabled" IsChecked="{Binding Path=IsEnabled, Mode=TwoWay}" />
</StackPanel>
Coordinator
Dec 14, 2012 at 12:58 PM

Yes, it won't work if the parameter is null.  If you think that a null might be passed, then it's best to use the non-generic version and instead use a property on the ViewModel to pass information into the method invoked via the command.