WPF CommandParameter is NULL when binding to element

1.8k views Asked by At

I am trying to bind the textbox text to Commandparameter. However in the call to CanExecute the parameter passed is null. Changing the text also does not call CanExecute.

Is my use case valid ?

View

<Window x:Class="PlayButtonCommandParameter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:playButtonCommandParameter="clr-namespace:PlayButtonCommandParameter"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <playButtonCommandParameter:TestViewModel x:Key="vm"/>
  </Window.Resources>
    <StackPanel DataContext="{StaticResource vm}">
      <TextBox Name="Test">Hello</TextBox>
      <Button Content="Element Name Click" 
              Command="{Binding TestCommand}" 
              CommandParameter="{Binding ElementName=Test, Path=Text}"></Button>
      <Button Content="RelativeSource Click" 
              Command="{Binding RelativeSourceCommand}" 
              CommandParameter="{Binding 
                                  RelativeSource={RelativeSource AncestorType=StackPanel}, 
                                  Path=Children[0].Text}"></Button>
    </StackPanel>
</Window>

ViewModel

public class TestViewModel : INotifyPropertyChanged
{
    private readonly ICommand testCommand = new TestCommand();

    public ICommand TestCommand
    {
        get { return testCommand; }
    }

    private readonly ICommand relativeSourceCommand = new TestCommand();

    public ICommand RelativeSourceCommand
    {
        get { return relativeSourceCommand; }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Command

public class TestCommand : ICommand
{
    public void Execute(object parameter)
    {
        Clipboard.SetData(DataFormats.Text, parameter);
    }

    public bool CanExecute(object parameter)
    {
        var text = parameter as string;

        return !string.IsNullOrEmpty(text);
    }

    public event EventHandler CanExecuteChanged;
}
1

There are 1 answers

0
Novitchi S On

No your expectations are not valid. First:

Changing the text also does not call CanExecute

no one is going to call your CanExecute handler unless you fire the CanExecuteChanged event in your ICommand. In your case you will have to handle yourself the TextBox TextChanged event and raise the CanExecuteChanged from within your ICommand implementation.

For this simple case i would suggest you to use a instance of a RoutedCommand instead. There is a CommandManager that listens for changes in the UI and will raise the CanExecuteChanged event for you.

Just follow this simple steps How to: Create a RoutedCommand