WPF 標準コントロールデモアプリ › DataGrid

DataGrid List

DataGrid はコレクションを行と列の表として表示するコントロールです。列の並べ替え、その場での編集、行の追加と削除を標準で備えています。

自動で作られる列

DataGrid は MultiSelector・Selector・ItemsControl を継承しています。既定の AutoGenerateColumns="True" では、バインドできる公開プロパティごとに 1 列を作ります。Zeta・Alpha・Mid の順に宣言した計測のクラスでは、アルファベット順ではなく宣言した順に列ができました。この順序は観測した結果で、ドキュメントが保証するものではありません。セッターのないプロパティは読み取り専用の列になりました。

計測した項目の型では、公開プロパティはすべて列になり、インデクサー this[string columnName] は列になりませんでした。デモアプリの項目は IDataErrorInfo を実装しているため、自動で作られた列は Name・Value と、インターフェイスから来た読み取り専用の Error 列でした。見せたくないメンバーがある型では、AutoGenerateColumns を False にし、DataGridTextColumn・DataGridCheckBoxColumn・DataGridComboBoxColumn などで列を宣言します。編集中のセルには、それぞれ TextBox・CheckBox・ComboBox が入りました。

行の追加・削除と、読み取り専用の表

CanUserAddRows と CanUserDeleteRows は、最下部の空の行から行を追加できるか、選んだ行を Delete キーで削除できるかです。どちらも既定値は True です。新規行はソースによって変わりました。List<T> と ObservableCollection<T> では表示され、配列と引数なしのコンストラクターを持たない型では表示されませんでした。その場合、CanUserAddRows は例外を出さずに False になったので、ユーザーが行を追加できない場合はソースを確認します。3 行のうち 2 行目を選んで Delete キーを押すと、その行がソースのコレクションから削除されました。

IsReadOnly は表全体の編集を止めます。IsReadOnly="True" にすると、CanUserAddRows は False になりました。列の側から編集を許すことはできません。列に IsReadOnly="False" を明示すると、列の値は False のままでしたが、そのセルで BeginEdit() を呼ぶと False が返り、編集は始まりませんでした。

条件 計測値
自動生成の列、宣言は Zeta、Alpha(get のみ)、Mid Zeta(編集できる)、Alpha(読み取り専用)、Mid(編集できる)
自動生成の列、デモの SampleItem(IDataErrorInfo) Name(編集できる)、Value(編集できる)、Error(読み取り専用)
2 列、FrozenColumnCount = 3(デモのスライダーの最大値) 例外なし、表示できる、値 2
デモのデータ、3 行目に Error、RowValidationRules 空: HasError の最初 / 編集後 False / False
デモのデータ、3 行目に Error、RowValidationRules + DataErrorValidationRule: HasError の最初 / 編集後 True / True
DataGrid が IsReadOnly=True: CanUserAddRows False (Default)
列に IsReadOnly=False を指定: IsReadOnly / BeginEdit() False / False
新規行 / CanUserAddRows、ItemsSource List<Person> 表示される / True
新規行 / CanUserAddRows、ItemsSource ObservableCollection<Person> 表示される / True
新規行 / CanUserAddRows、ItemsSource Person[](配列) 表示されない / False
新規行 / CanUserAddRows、ItemsSource 引数なしのコンストラクターが無い型の List<T> 表示されない / False
2 行目を選んで Delete キー: 残った項目 2 (Name 1, Name 3)

列、読み取り専用の設定、検証、行の追加と削除。.NET 10 / Windows 11 で計測。

行の検証には規則が要る

RowValidationErrorTemplate は、行の検証に失敗したときの表示です。行が検証に失敗するのは規則が行を調べたときだけで、RowValidationRules は既定では空です。デモアプリのデータでは 3 行目が IDataErrorInfo.Error を返しますが、この行は編集した後も Validation.HasError になりませんでした。そのため、このデータで規則が無いままでは、テンプレートは表示されませんでした。RowValidationRules に DataErrorValidationRule を加えると、3 行目は検証エラーになりました。行にエラーを表示するなら、検証の規則を加えます。

編集と、編集中の並べ替え

フォーカスのある Name のセルで、キーボードでの編集を測りました。F2 キーで編集が始まり、セルに TextBox が入りました。”Changed” と入力して Esc キーを押すと、編集が終わり、ソースは変わりませんでした。もう一度 F2 キーを押して “Committed” と入力し、Enter キーを押すと、ソースに “Committed” が書き込まれました。

並べ替えは標準の機能です。列見出しをクリックすると昇順、もう一度で降順、3 回目で再び昇順になりました。3 回目で並べ替えが解除されるわけではありません。コードから解除する方法はWPFのDataGridのソートを初期化する方法で扱っています。

セルの編集中に項目へ SortDescription を加えると、InvalidOperationException が発生しました。引数なしの CommitEdit() や CancelEdit() を呼んでも防げず、どちらの後でも並べ替えで例外が発生しました。CommitEdit(DataGridEditingUnit.Row, true) か CancelEdit(DataGridEditingUnit.Row) の後は並べ替えられました。コードから並べ替え・絞り込み・グループ化をする前に、このように行の編集を終えます。

グループ化はコレクションビューの機能で、DataGrid がグループを表示するのは GroupStyle があるときだけです。GroupStyle がないと、グループ化したビューでもグループの見出しは現れませんでした。

画面上の行:仮想化、列の固定、1 行おきの背景

EnableRowVirtualization は、表示範囲外の DataGridRow のコンテナーを作らないかどうかです。EnableColumnVirtualization は DataGridColumn の定義には関わらず(定義は常に保たれる)、表示範囲外の列のセルと列見出しを作らないかどうかを決めます(列の仮想化はここでは測っていません)。既定値は行が True、列が False です。幅 360、高さ 200 の DataGrid に 1,000 行を入れると、DataGridRow は 11 個でした。既定では VirtualizingPanel.IsVirtualizingWhenGrouping が False なので、グループ化すると行の仮想化は止まり、GroupStyle を付けてグループ化すると 1,000 行すべてが作られました。同じ DataGrid でこれを True にすると、作られた行は 18 個でした。グループ化する表には設定します。

FrozenColumnCount は、横スクロールのときに動かさない、左端からの列の数です。既定値は 0 です。幅 200 の DataGrid に幅 100 の列を 4 つ並べて右へ 60 スクロールすると、1 列目は x = 7 から -53 へ動きました。FrozenColumnCount="1" では 1 列目は 7 のままで、2 列目だけが動きました。2 列に 3 を設定しても例外は出ず、2 に補正されました。

AlternatingRowBackground は 1 行おきの背景です。このプロパティだけを設定すれば足ります。AlternationCount は 2 になり、4 行が白と指定したブラシで交互になりました。

条件 計測値
Name のセルで F2: IsEditing / 編集用の要素 True / TextBox
"Changed" を入力して Esc: IsEditing / ソース False / "Name 1"
F2、"Committed" を入力して Enter: ソース "Committed"
列の種類ごとの編集用の要素 Text: TextBox, CheckBox: CheckBox, ComboBox: ComboBox
Name の見出しを 3 回クリック: SortDirection Ascending -> Descending -> Ascending
セルの編集中に Items.SortDescriptions.Add(...) InvalidOperationException
CommitEdit() の後 InvalidOperationException
CancelEdit() の後 InvalidOperationException
CommitEdit(DataGridEditingUnit.Row, true) の後 例外なし
CancelEdit(DataGridEditingUnit.Row) の後 例外なし
AlternatingRowBackground だけを指定: AlternationCount / 各行 2 / #FFFFFFFF, #FFD3D3D3, #FFFFFFFF, #FFD3D3D3
1,000 行: DataGridRow の数 / GroupItem の数 11 / 0
1,000 行をグループ化、GroupStyle あり: DataGridRow の数 / GroupItem の数 1000 / 10
1,000 行をグループ化、GroupStyle なし: DataGridRow の数 / GroupItem の数 11 / 0
1,000 行をグループ化、GroupStyle、IsVirtualizingWhenGrouping=True: DataGridRow の数 / GroupItem の数 18 / 1
FrozenColumnCount=0、60 スクロール: 1 列目と 2 列目の x 座標 前 / 後 7, 107 / -53, 47
FrozenColumnCount=1、60 スクロール: 1 列目と 2 列目の x 座標 前 / 後 7, 107 / 7, 47

編集、並べ替え、1 行おきの背景、仮想化、列の固定。.NET 10 / Windows 11 で計測。

そのほかの切り替えの既定値

デモアプリで試す

デモアプリの DataGrid のページ。左にコントロールの一覧、右に最初の節の AlternatingRowBackground

デモアプリの DataGrid のページには、ここまでのプロパティをすべて含む 20 のプロパティのまとまりごとに欄があります。データは Name と Value を持ち、IDataErrorInfo を実装した項目です。FrozenColumnCount のスライダーは、列が 2 つなのに 3 まで選べます。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、FrozenColumnCount の欄(DataGridUsageControl.xaml)から、スタイルと周囲の GroupBox を省き、名前空間の宣言を加えたものです。Items は Name と Value を持つ項目のコレクションです。この断片は継承した DataContext を前提にしています。デモアプリでは DataGridUsageControl が Items を持つビューモデルを DataContext に設定しているので、断片だけで使う場合は、対応する DataContext を設定します。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Slider x:Name="PropertyFrozenColumnCount"
          IsSnapToTickEnabled="True" Maximum="3" Minimum="0" />

  <DataGrid x:Name="ResultFrozen" Height="150"
            AutoGenerateColumns="False"
            FrozenColumnCount="{Binding Value, ElementName=PropertyFrozenColumnCount}"
            ItemsSource="{Binding Items}">
    <DataGrid.Columns>
      <DataGridTextColumn Width="150" Binding="{Binding Name}" Header="Frozen" />
      <DataGridTextColumn Width="600" Binding="{Binding Value}" Header="Scrollable" />
    </DataGrid.Columns>
  </DataGrid>
</StackPanel>

関連するコントロールと記事

ソースコードと計測の方法

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの DataGridDemoScene を使いました。列見出しのクリックは見出しのクリック処理(OnClick)を呼び、キー操作は表示したウィンドウへキーのイベントを送って再現しました。位置は計測した環境での値です。

GitHub で DataGrid のソースコードを見る →