WPFプログラミング備忘録

WPF DataGridの行を取得する

WPF

私は WPF DataGridの行の扱い方を忘れがちで、必要になるたびにネット検索や手持ちのソースコードを参照する羽目になってしまいます。

そこで、この記事ではWPFのDataGridに表示されている行の情報を取得する方法について記載しておきました。

まず画面の XAML ファイルを以下に示します。

<Window x:Class="WpfDataGridSample.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:WpfDataGridSample"
        mc:Ignorable="d"
        Title="DataGridSample" Height="250" Width="300"
        Loaded="Window_Loaded">
    <Grid>
        <DataGrid x:Name="dataGrid" 
                  AutoGenerateColumns="False" 
                  CanUserSortColumns="False" 
                  CanUserAddRows="False" 
                  SelectionMode="Single" 
                  SelectionUnit="FullRow"
                  PreviewKeyDown="dataGrid_PreviewKeyDown">
            <DataGrid.Columns>
                <DataGridTextColumn Header="氏名" Binding="{Binding FullName}" Width="120" IsReadOnly="True" CanUserSort="False" />
                <DataGridTemplateColumn Header="誕生日" Width="120" CanUserSort="False">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <DatePicker SelectedDate="{Binding BirthDay, StringFormat=yyyy/MM/dd, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

氏名と誕生日の2列を定義しました。氏名は DataGridTextColumn です。誕生日は DatePickerです。ここでのポイントは誕生日を表現するために DatePicker を使用したいため DataGridTemplateColumn を使用していることです。また SelectionUnit を “FullRow” にしているため任意のセルをクリックすると、そのセルを含む行全体が選択されます。

検証のため誕生日ですが変更可能にしてあります。

今回は選択されている行でリターンキーを押すとその行の各セルの値を取得し、メッセージボックスに整形した文字列を表示することにしました。

なおコードが長くなるのでセルに装飾はしていません。セルに色を着ける方法は以下の記事をご確認ください。

>>WPF DataGridのセルに色を付けよう

コードビハインドを以下に示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfDataGridSample
{
    public class Person
    {
        public string FullName { get; set; }
        public DateTime? BirthDay { get; set; }
        public Person(string fullName, DateTime birthDay)
        {
            FullName = fullName;
            BirthDay = birthDay;
        }
    }

    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public List<Person> people = new List<Person>();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            people.Add(new Person("山田 太郎", new DateTime(2002, 5, 18)));
            people.Add(new Person("鈴木 花子", new DateTime(2004, 11, 6)));
            people.Add(new Person("畠山 銀次", new DateTime(1982, 7, 2)));

            dataGrid.ItemsSource = people;
        }

        // 選択されている行番号を取得する
        private int GetCurrentRowNumber(DataGrid dg)
        {
            int row = 0;
            try
            {
                row = dg.Items.IndexOf(dg.CurrentItem);
            }
            catch
            {
                row = -1;
            }

            return row;
        }

        // 選択されている列番号を取得する(今回は使用しない)
        private int GetCurrentColumnNumber(DataGrid dg)
        {
            int col = -1;
            DataGridCellInfo cellInfo = dg.CurrentCell;
            
            if (cellInfo.Column != null)
            {
                col = cellInfo.Column.DisplayIndex;
            }

            return col;
        }

        private void dataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            int rowNumber = GetCurrentRowNumber(dataGrid);

            if(rowNumber < 0)
            {
                return;
            }

            if(e.Key == Key.Return)
            {
                // 行番号からDataGridRowオブジェクトを取得する
                DataGridRow dataGridRow = dataGrid.ItemContainerGenerator.ContainerFromIndex(rowNumber) as DataGridRow;

                if(dataGridRow == null)
                {
                    return;
                }

                // DataGridRow.Itemプロパティから取得されるobject型をユーザー定義型にキャストする
                Person person = dataGridRow.Item as Person;

                if(person != null && person.BirthDay.HasValue)
                {
                    MessageBox.Show(person.FullName + 
                                   "さんの誕生日は" + 
                                   person.BirthDay.Value.ToString("yyyy年MM月dd日") + 
                                   "です。");
                }
            }
        }
    }
}

氏名と誕生日を持つ Person クラスを定義しています。Loaded イベントハンドラの中では3人分の情報をDataGridに表示しています。

選択されている行の行番号は GetCurrentRowNumber メソッドで取得できます。また今回は使用しませんが、選択されているセルの列番号は GetCurrentColumnNumber メソッドで取得できます。

PreviewKeyDownイベントハンドラでは選択されているアクティブな行の情報を取得して整形した文字列をメッセージボックスに出力しています。

上記のプログラムの実行結果は以下のとおりです。

次に2行目を選択した結果は以下のとおりです。

この状態でリターンキーを押すと以下のダイアログボックスが表示されます。

関連記事

>> WPF DataGridの行をフィルタリングする

>> WPF DataGridの行をグループ化する

>> WPF DataGridの行を入れ替える

>> WPF DataGridのセルに色を付けよう

最後に参考書籍について紹介致します。

以下の2冊はWPFの機能が網羅的にまとめられています。基礎から応用までバランス良く解説されており手元に置いておくと何かと重宝します。洋書ですが平易な英語で書かれておりプログラムコードとの比率も適切で、英語が苦手な方でも読めると思いますのでお勧めします。

以上です。

コメント