Search code examples
c#wpfdatagridhotkeys

CTRL + C is not detected in WPF DataGrid


I have a WPF applicaiton where the MainWindow class have <Window.CommandBindings> and <Window.InputBindings> so I can detect CTRL + X, CTRL + C and CTRL + V commands.

The MainWindow contains a DataGrid where I want to select a row and copy the data in the row with the CTRL + C command. When a row is selected in the DataGrid the CTRL + C command is no longer detected in the MainWindow. CTRL + X and CTRL + V are still detected.

I have managed to reproduce this problem with a very simple example. Just copy and paste the code below, it should compile and run on the go. Then do the following:

  1. Press either CTRL + X, CTRL + C or CTRL + V: A popup window will say what command was activated.
  2. Select a row in the DataGrid and then press CTRL + C: Nothing will happen.
  3. CTRL + X or CTRL + V will still be detected.

MainWindow.XAML code

<!-- Commands for hot keys -->
<Window.CommandBindings>

    <!-- Source -->
    <!-- http://stackoverflow.com/questions/4682915/defining-menuitem-shortcuts -->

    <CommandBinding Command="Cut" Executed="btnCut_Click" />
    <CommandBinding Command="Copy" Executed="btnCopy_Click" />
    <CommandBinding Command="Paste" Executed="btnPaste_Click" />

</Window.CommandBindings>

<!-- Hot keys -->
<Window.InputBindings>
    <KeyBinding Key="X" Modifiers="Control" Command="Cut" />
    <KeyBinding Key="C" Modifiers="Control" Command="Copy" />
    <KeyBinding Key="V" Modifiers="Control" Command="Paste" />
</Window.InputBindings>

<Grid>
    <DataGrid Name="dgPersons" HorizontalScrollBarVisibility="Auto" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Extended" GridLinesVisibility="None" Background="White" Margin="75,59,35,104">

        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Setter Property="BorderThickness" Value="0" />
                <Setter Property="FocusVisualStyle" Value="{x:Null}" />
            </Style>
        </DataGrid.CellStyle>

        <DataGrid.Columns>

            <!-- Name -->
            <DataGridTextColumn Header="Name" Width="100" Binding="{Binding Name, Mode=OneTime}" />

        </DataGrid.Columns>
    </DataGrid>
</Grid>

MainWindow.cs code

public partial class MainWindow : Window
{
    ObservableCollection<Person> persons = new ObservableCollection<Person>();

    public MainWindow()
    {
        InitializeComponent();

        Person person1 = new Person("Person1");
        Person person2 = new Person("Person2");
        Person person3 = new Person("Person3");

        persons.Add(person1);
        persons.Add(person2);
        persons.Add(person3);

        dgPersons.ItemsSource = persons;
    }

    private void btnCut_Click(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("CUT command activated");
    }

    private void btnCopy_Click(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("COPY command activated");
    }

    private void btnPaste_Click(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("PASTE command activated");
    }
}

public class Person
{
    string name;

    public Person(string name)
    {
        this.name = name;
    }

    public string Name
    {
        get { return name; }
    }
}

How do I get CTRL + C working when a row is selected in the DataGrid?


Solution

  • I solved it by including Command and Input Bindings in the DataGrid itself:

    <DataGrid>
        <!-- This is required to handle CTRL + C when something is selected in the DataGrid -->
        <DataGrid.CommandBindings>
            <CommandBinding Command="Copy" Executed="CopyCommand" />
        </DataGrid.CommandBindings>
    
        <!-- This is required to handle CTRL + C when something is selected in the DataGrid -->
        <DataGrid.InputBindings>
            <KeyBinding Key="C" Modifiers="Control" Command="Copy" />
        </DataGrid.InputBindings>
    </DataGrid>
    

    Then a callback in the code to handle the event from CTRL + C.

        /// <summary>
        /// Handle CTRL + C callback
        /// </summary>
        private void CopyCommand(object sender, ExecutedRoutedEventArgs e)
        {
            // Do copy here
        }