I need to implement a custom copy + cut + paste for data (not text or CSV) that needs to be copied between grids in a WPF application. Using standard ApplicationCommands and defining CommandBinding works very well, but only if the DataGrid contains at least 1 row of data and when it is selected. When there are no lines or focus is not on any of them, all commands are disabled.
To fix the problem, I tried calling CommandManager.InvalidateRequerySposed () and setting Focusable = true and / or FocusManager.IsFocusScope = true in the DataGrid, but it seems that the DataGrid as a whole is “not interested” in processing copy / paste operations, only its rows represent CanExecute re-query commands and invoke Execute accordingly. It also ignores KeyBindings.
How to force the DataGrid handler to request ApplicationCommands?
Please find an example on which I tested the problem below:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DataGrid x:Name="TheGrid"> <DataGrid.Columns> <DataGridTextColumn Header="Number" Binding="{Binding}"/> </DataGrid.Columns> <DataGrid.InputBindings> <KeyBinding Key="A" Command="{x:Static ApplicationCommands.New}"/> </DataGrid.InputBindings> <DataGrid.CommandBindings> <CommandBinding Command="{x:Static ApplicationCommands.Paste}" CanExecute="CanPaste" Executed="Paste"/> <CommandBinding Command="{x:Static ApplicationCommands.Copy}" CanExecute="CanCopy" Executed="Copy"/> <CommandBinding Command="{x:Static ApplicationCommands.New}" CanExecute="CanAddNew" Executed="AddNew"/> </DataGrid.CommandBindings> <DataGrid.ContextMenu> <ContextMenu> <MenuItem Command="{x:Static ApplicationCommands.Copy}" Header="Copy"/> <MenuItem Command="{x:Static ApplicationCommands.Paste}" Header="Paste"/> <MenuItem Command="{x:Static ApplicationCommands.New}" Header="New row"/> </ContextMenu> </DataGrid.ContextMenu> </DataGrid> </Window>
And the code behind:
using System.Collections.Generic; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Input; namespace WpfApplication1 { public partial class MainWindow { public MainWindow() { InitializeComponent(); TheGrid.ItemsSource = numbers;
Edit
Ayyappan Subramanian's code-only solution is the closest to the application in which it will be used. In the end, since I already inherit the grid, because it has its own copy + paste format, I added code that ensures that the focus is in the grid in 3 cases:
- The context menu is displayed.
- The user clicks in the grid area (empty) when the child images have no focus.
- (our specific case for the application) The user clicks on the TreeView selector navigation, which is then focused on the grid, so the shortcuts will work immediately.
Relevant Code:
public class MyDataGrid: DataGrid { protected override void OnContextMenuOpening(ContextMenuEventArgs e) { base.OnContextMenuOpening(e); Focus(); } protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if(e.ChangedButton == MouseButton.Left && !IsKeyboardFocusWithin) { Focus(); } } }
source share