Search code examples
c#wpfxamldatagridkey-bindings

WPF disable default keybinding on DataGrid (as if it was never defined)


I would like to disable some of the default behaviours of DataGrid keys in order to override it with my own improved commands. How can I disable DataGrid's keybinds as if they were never defined in the first place?

For example, Enter key jumps to new row by default, I would like to focus item detail control instead. Stopping the event is easy enough with this.handled = true; that, however also prevents any custom Commands from happening, minimal example of the problem:

public partial class MainWindow : Window
{
    public class Model {
        public string Name { get; set; }
        public int Value { get; set; }
    }

    public class TestCommand : ICommand {
        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) => true;
        public void Execute(object parameter) => MessageBox.Show("Command invoked");
    }

    public ICommand EnterCommand { get; } = new TestCommand();
    public IEnumerable<Model> Items {
        get { return new List<Model>() {
                new Model { Name = "Foo", Value = 15 },
                new Model { Name = "Bar", Value = 1 },
                new Model { Name = "Baz", Value = 42 },
                new Model { Name = "Bar", Value = 100 } }; }
    }

    public MainWindow() { InitializeComponent(); }

    private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter) e.Handled = true;
    }
}

//MainWindow.xaml, Window.Name = "Root"
<Window.InputBindings>
    <KeyBinding Key="Enter" Command="{Binding EnterCommand, ElementName=Root}"/>
</Window.InputBindings>
<DataGrid ItemsSource="{Binding Items, ElementName=Root}" PreviewKeyDown="DataGrid_PreviewKeyDown"/>

When Enter key is pressed while DataGrid is focused, EnterCommand should be invoked via <KeyBinding/> i.e. without explicit reference in codebehind (ViewModel ommited for brewity) and DataGrid's default behaviour prevented, i.e. not jumping to next row.


Solution

  • You could programmatically raise another KeyDownEvent event once you have handled the DataGrid's PreviewKeyDown event:

    private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            e.Handled = true;
            RaiseEvent(new KeyEventArgs(Keyboard.PrimaryDevice, PresentationSource.FromVisual(this), 0, Key.Enter)
            {
                RoutedEvent = Keyboard.KeyDownEvent
            });
        }
    }