DataGridコントロールのカスタマイズ
Windows Community ToolkitのDataGridは、列定義をカスタマイズしたり、ソート機能を追加したりできます。
列定義をカスタマイズする
列の定義を次のようにカスタマイズしてみましょう。
- 特定の列だけを表示する
- 列ヘッダーの表示をプロパティ名とは変える
- 特定の列は編集を禁止する
それには、DataGridコントロールのAutoGenerateColumnsプロパティをFalseに変更した上で、次のコードのように列定義を追加します。ここではDataGridTextColumn(テキストを表示する列)だけを使っていますが、他にDataGridCheckBoxColumn(Nullable<bool>型をバインドするチェックボックス列)とDataGridTemplateColumn(データテンプレートで自由にデザインする列)があります(さらにWindows Community Toolkitバージョン5.0でComboBoxColumnが追加されました)。
<tk:DataGrid x:Name="dataGrid" AutoGenerateColumns="False"
GridLinesVisibility="All" AlternatingRowBackground="LightCyan">
<tk:DataGrid.Columns>
<tk:DataGridTextColumn
Header="ID" Binding="{Binding 作品ID}" Tag="作品ID" IsReadOnly="True" />
<tk:DataGridTextColumn
Header="作品名" Binding="{Binding 作品名}" Tag="作品名" />
<tk:DataGridTextColumn
Header="文字遣い" Binding="{Binding 文字遣い種別}" Tag="文字遣い種別" />
<tk:DataGridTextColumn
Header="著者" Binding="{Binding 姓名}" Tag="姓名" IsReadOnly="True" />
</tk:DataGrid.Columns>
</tk:DataGrid>
DataGridTextColumnのHeaderプロパティが、列ヘッダーに表示される文字列です。IsReadOnlyプロパティをTrueにすると、その列は編集禁止になります。なお、Tagプロパティも追加してありますが、これは次のソート機能で利用するためです。
これで、次の画像のように表示されるようになりました。
ソートをサポートする
DataGridの列ヘッダーをクリックするとSortingイベントが発生します。そのイベントハンドラーでソートを行う処理を書けばよいのです。また、列オブジェクトはSortDirectionプロパティを持っていて、これを設定することで列ヘッダーにソート方向(昇順/降順)を示すマークを表示できます。
XAMLの修正
次のようにSortingイベントハンドラーを追加します。
<tk:DataGrid x:Name="dataGrid" AutoGenerateColumns="False"
GridLinesVisibility="All" AlternatingRowBackground="LightCyan"
Sorting="DataGrid_Sorting"
>
AdvancedCollectionViewクラス
さて、ソート処理は、WPFならCollectionViewSourceを使ってサクっとできました。残念ながらUWPのCollectionViewSourceにはソート機能がありません。どうしたものでしょう?
これまたWindows Community Toolkitに、WPFのCollectionViewと同じように使えるAdvancedCollectionViewクラスがあります(Microsoft.Toolkit.Uwp.UI名前空間)。
DataGridのItemsSourceプロパティに与えるコレクションを、次のコードのようにAdvancedCollectionViewクラスに変更しておきます。
private ObservableCollection<Data.AozoraBunko> _observableCollection;
private AdvancedCollectionView _advancedCollectionView;
private async void LoadAozoraBunkoDataAsync()
{
IEnumerable<Data.AozoraBunko> list = ……省略(データを取得する)……
_observableCollection = new ObservableCollection<Data.AozoraBunko>(list);
_advancedCollectionView
= new AdvancedCollectionView(_observableCollection, true);
this.dataGrid.ItemsSource = _advancedCollectionView;
}
Sortingイベントハンドラー
実際にソートを行う処理を書いていきます。
まず、どのプロパティをソートに使うかを決めておきます。例えば、[作品名]列ヘッダーをクリックされたときには、[作品名]ではなく、[作品名読み]を使ってソートしたいのです。そこで、次のコードのようなテーブルを定義しておきます。
private readonly Dictionary_sortTargets = new Dictionary<string, string> { { "作品ID", "作品ID" }, { "作品名", "作品名読み" }, { "文字遣い種別", "文字遣い種別" }, { "姓名", "姓名読み" }, };
ソートするには、「どのプロパティを使って、昇順/降順どちらにソートするのか」を表すSortDescriptionオブジェクトを作って、それをAdvancedCollectionViewのSortDescriptionsプロパティに挿入してやります。SortDescriptionsプロパティには複数のSortDescriptionオブジェクトを設定できて、その際には先頭にあるSortDescriptionオブジェクトが優先されてソートされます。そこで、クリックされた列を優先してソートするために、その列のSortDescriptionオブジェクトをSortDescriptionsプロパティの先頭に挿入します。
Sortingイベントハンドラーの全体は、次のコードのようになります。
private async void DataGrid_Sorting(object sender, DataGridColumnEventArgs e)
{
// ソートに使うプロパティ名(例:[作品名]をクリックされたら[作品名読み]でソート)
string sortTarget = _sortTargets[e.Column.Tag as string];
// クリックされた列の、現在のソート方向を取得する
var currentSortDirection = e.Column.SortDirection;
// 全ての列ヘッダーのソートマーク(「↑」/「↓」)を消す
foreach (var c in this.dataGrid.Columns)
c.SortDirection = null;
// AdvancedCollectionViewから、以前のSortDescriptionオブジェクトを削除する(もしあれば)
var oldSort = _advancedCollectionView.SortDescriptions
.FirstOrDefault(s => s.PropertyName == sortTarget);
if (oldSort != null)
_advancedCollectionView.SortDescriptions.Remove(oldSort);
if (currentSortDirection == null
|| currentSortDirection == DataGridSortDirection.Descending)
{
// 現在、未ソートまたは降順にソートされているなら、
// 昇順にソート(新しいSortDescriptionオブジェクトを先頭に挿入する)
_advancedCollectionView.SortDescriptions
.Insert(0, new SortDescription(sortTarget, SortDirection.Ascending));
// 列ヘッダーにソートマーク「↑」を付ける
e.Column.SortDirection = DataGridSortDirection.Ascending;
}
else
{
// 現在、昇順にソートされているなら、
// 降順にソート(新しいSortDescriptionオブジェクトを先頭に挿入する)
_advancedCollectionView.SortDescriptions
.Insert(0, new SortDescription(sortTarget, SortDirection.Descending));
// 列ヘッダーにソートマーク「↓」を付ける
e.Column.SortDirection = DataGridSortDirection.Descending;
}
}
これで、次の画像のようにソートができます。この例は、作品名で昇順にソートしてから、作者名で降順にソートしました。
行の詳細(Row Details)
DataGridコントロールは、行ごとにその詳細を表示することもできます。本稿のサンプルコードには実装してありませんが、例えばWindows Community Toolkit Sample Appをご覧ください(次の画像)。
このように、Windows 10 1703(15063)から利用できるDataGridコントロールは、高機能で簡単に使えます。さらに、サンプルコードをリリースビルドして確かめてほしいのですが、表示やソートも十分に高速です。
