WPFアプリで、DataGridコントロールやListViewコントロールにソートして表示されているデータが修正されたときに、再ソートしてデータが正しい順序で表示されるようにする方法を解説する。
対象:.NET 4.5以降
WPFのDataGridコントロールやListViewコントロールなど(いずれもSystem.Windows.Controls名前空間)に表示しているデータをソート/フィルタリング/グルーピングするには、CollectionViewSourceクラス(System.Windows.Data名前空間)を利用すればよい(「.NET TIPS:WPF:DataGridやListViewなどにデータをソートして表示するには?[XAML、C#、VB]」を参照)。ところが1つ困ったことがある。表示している元データをプログラムから変更したときには、表示位置が変わらず、ソート/フィルタリング/グルーピングが崩れてしまうのだ。これは簡単に解決できないものだろうか? 本稿では、.NET Framework 4.5の新機能を使ってこの問題に対処する方法を説明する。
なお、本稿のプログラミングには、無償のVisual Studio Express 2012 for Windows Desktop(以降、VS 2012)を使用した。Visual Studio 2013でも手順は同じである。
「.NET TIPS:WPF:DataGridやListViewなどにデータをソートして表示するには?[XAML、C#、VB]」で作成したプログラムを準備していただきたい。以降では、これをベースにして説明する。
ソートが設定してあると、DataGridコントロール上でエンドユーザーが直接編集/追加した場合や、プログラムからデータを追加した場合は、表示されているデータが自動的に適切な場所に移動し、ソート順が保たれていた。
ところが、プログラムからデータを変更した場合には、表示されているデータが移動しない。そのためソート順が崩れてしまう(次の画像)。
ICollectionViewLiveShapingインターフェース(System.ComponentModel名前空間)を使えばよい(.NET Framework 4.5の新機能)。
ただし、.NET Framework 4.5でICollectionViewLiveShapingインターフェースを実装しているのは、ListCollectionViewクラス/BindingListCollectionViewクラス(以上2つはSystem.Windows.Data名前空間)/ItemCollectionクラス(System.Windows.Controls名前空間)の3つである。上記のベースとなるプログラムにおいて、元データはObservableCollectionクラスであり、そこから得られる既定のビューはListCollectionViewクラスであるので、このICollectionViewLiveShapingインターフェースの機能を利用できる。
コーディングとしては、既定のビューのIsLiveSortingプロパティをtrueにするだけである(次のコード)。
// 画面が表示されるとき、データを画面にセットする
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// 既定のビューを取り出してセットする
var view = CollectionViewSource.GetDefaultView(_data);
this.RootGrid.DataContext = view;
// 既定のビューにソートを指定する
view.SortDescriptions.Add(
new System.ComponentModel.SortDescription(
"Value",
System.ComponentModel.ListSortDirection.Ascending)
);
// DataGridコントロールのヘッダーにソートの印(三角のマーク)を表示する
this.DataGrid1.Columns[1].SortDirection = System.ComponentModel.ListSortDirection.Ascending;
// ここまでが、ベースとなるプログラムの記述
// LiveShapingを有効にする
// viewの実体が分からないときは、ICollectionViewLiveShapingインターフェースが実装されていることと、
// CanChangeLiveSortingプロパティの値がtrueであるかをチェックしてから有効にすること
var liveShaping = view as System.ComponentModel.ICollectionViewLiveShaping;
if (liveShaping != null && liveShaping.CanChangeLiveSorting)
liveShaping.IsLiveSorting = true;
// IsLiveSortingプロパティをtrueに変更できることが確定しているなら、次の1行で済む
//(view as System.ComponentModel.ICollectionViewLiveShaping).IsLiveSorting = true;
}
' 画面が表示されるとき、データを画面にセットする
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
' 既定のビューを取り出してセットする
Dim view = CollectionViewSource.GetDefaultView(_data)
Me.RootGrid.DataContext = view
' 既定のビューにソートを指定する
view.SortDescriptions.Add(
New System.ComponentModel.SortDescription(
"Value",
System.ComponentModel.ListSortDirection.Ascending)
)
' DataGridコントロールのヘッダーにソートの印(三角のマーク)を表示する
Me.DataGrid1.Columns(1).SortDirection _
= System.ComponentModel.ListSortDirection.Ascending
' ここまでが、ベースとなるプログラムの記述
' LiveShapingを有効にする
' viewの実体が分からないときは、ICollectionViewLiveShapingインターフェースが実装されていることと、
' CanChangeLiveSortingプロパティの値がTrueであるかをチェックしてから有効にすること
Dim liveShaping = TryCast(view, System.ComponentModel.ICollectionViewLiveShaping)
If (liveShaping IsNot Nothing AndAlso liveShaping.CanChangeLiveSorting) Then
liveShaping.IsLiveSorting = True
End If
' IsLiveSortingプロパティをtrueに変更できることが確定しているなら、次の1行で済む
'DirectCast(view, System.ComponentModel.ICollectionViewLiveShaping).IsLiveSorting = True
End Sub
これで実行してみると、次の画像のようにソート順が維持される。なお、同様にして、フィルタリング/グルーピングを維持させることもできる。
利用可能バージョン:.NET Framework 4.5以降
カテゴリ:WPF 処理対象:DataGridコントロール、ListViewコントロール
使用ライブラリ:ICollectionViewLiveShapingインターフェース(System.ComponentModel名前空間)
関連TIPS:WPF:DataGridやListViewなどにデータをソートして表示するには?[XAML、C#、VB]
Copyright© Digital Advantage Corp. All Rights Reserved.