none
DataGridのキー操作の変更 RRS feed

  • 質問

  • 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 +↓」の操作は⇒「現在の列の最後のセルにフォーカスを移動」ですが、これを「選択項目を増やす」ような操作にしたいと思っています。

    どのようにすると実現できるでしょうか。よろしくお願いいたします。

    2018年8月24日 11:51

回答

  • こんな

    <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
    2018年8月24日 14:11

すべての返信

  • こんな

    <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
    2018年8月24日 14:11
  • gekka様

    とても参考になりました。ありがとうございます!

    2018年8月29日 4:12