トップ回答者
DataGridのキー操作の変更

質問
-
DataGrid(https://msdn.microsoft.com/ja-jp/library/system.windows.controls.datagrid.aspx)のキー操作をいくつか変更したいと思っています。
例えば、DataGridの既定のキー操作(https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/controls/default-keyboard-and-mouse-behavior-in-the-datagrid-control)の中で、
「Ctrl +↓」の操作は⇒「現在の列の最後のセルにフォーカスを移動」ですが、これを「選択項目を増やす」ような操作にしたいと思っています。
どのようにすると実現できるでしょうか。よろしくお願いいたします。
回答
-
こんな
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" SelectionMode="Extended" PreviewKeyDown="DataGrid_PreviewKeyDown"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Path=Text}" IsReadOnly="true" Header="Column1"/> <DataGridTextColumn Binding="{Binding Path=Text}" IsReadOnly="false" Header="Column2"/> <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Text}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <TextBox Text="{Binding Path=Text}" Foreground="Red"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace WpfApp1 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var list = new List<Item>(); for (int i = 0; i < 1000; i++) { list.Add(new Item() { Text = i.ToString() }); }; this.DataContext = list; } private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.KeyboardDevice.Modifiers != ModifierKeys.Control) { return; } if (e.Key != Key.Down && e.Key != Key.Up) { return; } var dg = (DataGrid)sender; var cellInfo = dg.CurrentCell; var fe = cellInfo.Column.GetCellContent(cellInfo.Item); var cell = fe.Parent as DataGridCell; if (cell == null || cell.IsEditing) { return; } FocusNavigationDirection dir; switch (e.Key) { case Key.Down: dir = FocusNavigationDirection.Down; break; case Key.Up: dir = FocusNavigationDirection.Up; break; default: return; } var nextCell = cell.PredictFocus(dir) as DataGridCell; if (nextCell == null) { return; } object oCellDataContext = cell.DataContext; object oNextDataContext = nextCell.DataContext; if (dg.SelectedItems.Contains(nextCell.DataContext)) { dg.SelectedItems.Remove(cell.DataContext); } else { dg.SelectedItems.Add(nextCell.DataContext); } dg.CurrentCell = new DataGridCellInfo(nextCell); e.Handled = true; } private static object dataGridNewItemPlaceholder { get { if (_dataGridNewItemPlaceholder == null) { var pi = typeof(DataGrid).GetProperty("NewItemPlaceholder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); _dataGridNewItemPlaceholder = pi.GetValue(null); } return _dataGridNewItemPlaceholder; } } private static object _dataGridNewItemPlaceholder; } class Item { public string Text { get; set; } } }
#Shift+↑/↓でできるのでわざわざ実装する必要はないとは思いますが
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク yj0529 2018年8月29日 4:03
すべての返信
-
こんな
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" SelectionMode="Extended" PreviewKeyDown="DataGrid_PreviewKeyDown"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Path=Text}" IsReadOnly="true" Header="Column1"/> <DataGridTextColumn Binding="{Binding Path=Text}" IsReadOnly="false" Header="Column2"/> <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Text}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <TextBox Text="{Binding Path=Text}" Foreground="Red"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace WpfApp1 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var list = new List<Item>(); for (int i = 0; i < 1000; i++) { list.Add(new Item() { Text = i.ToString() }); }; this.DataContext = list; } private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.KeyboardDevice.Modifiers != ModifierKeys.Control) { return; } if (e.Key != Key.Down && e.Key != Key.Up) { return; } var dg = (DataGrid)sender; var cellInfo = dg.CurrentCell; var fe = cellInfo.Column.GetCellContent(cellInfo.Item); var cell = fe.Parent as DataGridCell; if (cell == null || cell.IsEditing) { return; } FocusNavigationDirection dir; switch (e.Key) { case Key.Down: dir = FocusNavigationDirection.Down; break; case Key.Up: dir = FocusNavigationDirection.Up; break; default: return; } var nextCell = cell.PredictFocus(dir) as DataGridCell; if (nextCell == null) { return; } object oCellDataContext = cell.DataContext; object oNextDataContext = nextCell.DataContext; if (dg.SelectedItems.Contains(nextCell.DataContext)) { dg.SelectedItems.Remove(cell.DataContext); } else { dg.SelectedItems.Add(nextCell.DataContext); } dg.CurrentCell = new DataGridCellInfo(nextCell); e.Handled = true; } private static object dataGridNewItemPlaceholder { get { if (_dataGridNewItemPlaceholder == null) { var pi = typeof(DataGrid).GetProperty("NewItemPlaceholder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); _dataGridNewItemPlaceholder = pi.GetValue(null); } return _dataGridNewItemPlaceholder; } } private static object _dataGridNewItemPlaceholder; } class Item { public string Text { get; set; } } }
#Shift+↑/↓でできるのでわざわざ実装する必要はないとは思いますが
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク yj0529 2018年8月29日 4:03