読者です 読者をやめる 読者になる 読者になる

Code for final

ふぁいなる向けのコード置き場です。すでにコードじゃないこともいっぱい。

WPFのDataGridで初期ソート(複数ソートキー)を設定する。

DataGrid WPF

WPFのDataGridで初期ソート(複数ソートキー)を設定したくなったので方法を調べてみました。

まず思いついたのが、DataGridにバインドしているObservableCollectionを並び替えて設定する方法ですが、 これは並び替えるたびにイベントが発火して遅いようです。
実際、実装しましたがワンテンポ遅れてソートされる感じでした。

次に、以下のようにDataGridTextColumnに"SortDirection"というプロパティがあったので設定してみました。ソートの矢印だけ表示されてソートはまったくされませんでした。
まぁ、使い方が間違っているのだけかもしれません。仮に出来たとしてもこのやり方では複数ソートキーは設定できない気がします。

<DataGridTextColumn Header="LastUpdate" SortDirection="Descending"></DataGridTextColumn>

さらに調べるとDataGridの初期ソート設定はCollectionViewSourceをかましてDataGridに設定するのがセオリーだみたいなことが書いてありました。
以下のような感じで書きました。
例はExplorerWindowCleanerから抜粋したコードですが、ピン留めを第1ソートキーに、更新日時を第2ソートキーとしてそれぞれ降順を設定しています。

<Window.Resources>
  <CollectionViewSource x:Key="NowExplorersView"  Source="{Binding NowExplorers}" >
    <CollectionViewSource.SortDescriptions>
      <componentModel:SortDescription PropertyName="IsPined" Direction="Descending" /> <!-- 第1ソートキー(ピン留め降順) -->
      <componentModel:SortDescription PropertyName="LastUpdateDateTime" Direction="Descending" /> <!-- 第2ソートキー(更新日時降順) -->
    </CollectionViewSource.SortDescriptions>
  </CollectionViewSource>
</Window.Resources>

<DataGrid Grid.Row="1" ItemsSource="{Binding Source={StaticResource NowExplorersView}}">
  ...(中略)
</DataGrid>

変更前はNowExplorersをDataGridにそのままバインドしていたので、CollectionViewSourceでワンクション置くようにした感じですかね。
これでバインドしているコレクションを変更するたびにソートが綺麗にかかるようになりました。

ただ、1つ問題がありました。バインドしているコレクションの中のオブジェクトのプロパティのみを変更した場合、再ソートされません。
上記の例でいうとピン留めのON/OFFだけ変わった場合です。
こういう場合はViewをリフレッシュするといいみたいです。
コードからFindResourceを使用してKey名を指定してXAMLに書いたCollectionViewSourceインスタンスを取得します。

var vs = this.FindResource("NowExplorersView") as CollectionViewSource; 
vs.View.Refresh();

もっといいやり方があるのかもしれないですけど、とりあえずこれで乗り切れました。