Andrew Truckle
Andrew Truckle

Reputation: 19207

Using the same command handler for button and keyboard

I am slowly giving myself another headache here ... Greymatter working ... :)

So I have a public delegate command in the model view:

public class OCLMEditorModelView : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private readonly DelegateCommand<string> _DeleteStudentButtonClickCommand;

    public ObservableCollection<Student> Students
    {
        get
        {
            return _Model.Students;
        }
    }

    private Student _SelectedStudentItem;
    public Student SelectedStudentItem
    {
        get { return _SelectedStudentItem; }
        set
        {
            _SelectedStudentItem = value;
            _EditStudentButtonClickCommand.RaiseCanExecuteChanged();
            _DeleteStudentButtonClickCommand.RaiseCanExecuteChanged();
            OnPropertyChanged("SelectedStudentItem");
        }
    }

    private OCLMEditorModel _Model;

    public OCLMEditorModelView()
    {
        _Model = new OCLMEditorModel();

        _DeleteStudentButtonClickCommand = new DelegateCommand<string>(
            (s) =>
            {
                String strMessage = String.Format(
                                   Properties.Resources.AreYouSure, _SelectedStudentItem.Name);

                if (AppMessageBox.Show(strMessage, 

                                   MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    _Model.Students.Remove(_SelectedStudentItem);
                    _Model.Serialize();
                }
            }, //Execute
            (s) => _SelectedStudentItem != null);  //CanExecute
    }

    // Create the OnPropertyChanged method to raise the event
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    public DelegateCommand<string> DeleteStudentButtonClickCommand
    {
        get { return _DeleteStudentButtonClickCommand; }
    }
}

The above gets handled when the user clicks the Delete button on the window:

 <Button Content="Delete" 
    Margin="2" 
    Command="{Binding DeleteStudentButtonClickCommand}"/>

All works well. So, I decided that i also wanted to support the Delete key. I have seen enough on the internet about using the PreviewKeyDown event.

So, I alter my DataGrid:

PreviewKeyDown="gridStudents_PreviewKeyDown"

And the handler:

private void gridStudents_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if(e.Key == Key.Delete)
    {
        if(gridStudents != null)
        {

        }
    }
}

This is where I am confused. At this point when I detect the Delete key I am in the code behind. But my own delete event handler is in the model view. I appreciate that I can replicate the code to do the delete from here here too.

But I am trying to find out how to use my existing command handler again.

So, I tried:

Error

I thought I could access the DataContext and cast it and then perhaps call it but it fails as you can see.

How can I use the same command handler in both places? From the Delete button on my window and the Delete key?

Thank you.

Upvotes: 0

Views: 60

Answers (1)

Jurica Smircic
Jurica Smircic

Reputation: 6455

There is a solution without a need for code behind. You can bind a Key to the same command delegate using an InputBindings collection.

  <Window.InputBindings>
    <KeyBinding Key="Delete" Command="{Binding DeleteStudentButtonClickCommand}"></KeyBinding>
  </Window.InputBindings>

Upvotes: 3

Related Questions