WPF:DataGridやListViewなどのデータを変更したときに自動的に再ソートするには?[C#、VB]:.NET TIPS
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コントロール上でエンドユーザーが直接編集/追加した場合や、プログラムからデータを追加した場合は、表示されているデータが自動的に適切な場所に移動し、ソート順が保たれていた。
ところが、プログラムからデータを変更した場合には、表示されているデータが移動しない。そのためソート順が崩れてしまう(次の画像)。
ベースとなるプログラムで、プログラムから元データを変更した(Windows 7)
最初は[VALUE]の昇順([Blue]→[Green]→[Red])にソートされている。その状態で、[Green]を[Yellow]に変更しようとしているところ(上)。
新しい値を入力し、画面右下の[Add/Renew]ボタンをクリックすると、コードビハインドのプログラムが元データを書き換える。表示は[Green]から[Yellow]に変わるが、ソートは行われず、表示位置は元のままだ(下)。
ヘッダーで[VALUE]の昇順になるようソートを指定しているのだから、[Yellow]に変わったデータは一番下に移動してほしいのだ。
データを変更したときに自動的にソートするには?
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
太字の部分を追加するだけである。
コメントにあるように、IsLiveSortingプロパティをtrueに変更できることが確実であるならば、1行だけで済む。
なお、このVBのコードでは、Visual Basic 2010から利用できるようになった「暗黙の行連結」を使用している。
これで実行してみると、次の画像のようにソート順が維持される。なお、同様にして、フィルタリング/グルーピングを維持させることもできる。
IsLiveSortingプロパティをtrueに変更して、プログラムから元データを変更した(Windows 7)
最初は[VALUE]の昇順([Blue]→[Green]→[Red])にソートされている。その状態で、[Green]を[Yellow]に変更しようとしているところ(上)。
画面右下の[Add/Renew]ボタンをクリックすると、コードビハインドのプログラムが元データを書き換える。表示内容とともに表示位置も自動的に変わり、ソート順が維持される(下)。
利用可能バージョン:.NET Framework 4.5以降
カテゴリ:WPF 処理対象:DataGridコントロール、ListViewコントロール
使用ライブラリ:ICollectionViewLiveShapingインターフェース(System.ComponentModel名前空間)
関連TIPS:WPF:DataGridやListViewなどにデータをソートして表示するには?[XAML、C#、VB]
Copyright© Digital Advantage Corp. All Rights Reserved.