Q124. XamDataGrid で絞り込み表示されてるレコードのみ抽出する(其の弐)
A.以前のエントリで、XamDataGrid で絞り込み表示されてるレコードのみ抽出する方法を紹介しましたが、これ一つ落とし穴がありまして、要素の描画タイミングによるのか、正常にレコードを取得できない場合があったりします。
関連記事:Q124. XamDataGrid で絞り込み表示されてるレコードのみ抽出する
例えば、XamDataGrid でフィルタリング実行時のイベント内で、絞り込まれたレコードのみ抽出したい場合、こんなコードになるかと思います。
レコード数やフィールドの少ない簡単な画面ならこれでも問題ありません。ところがレコード数が多かったり、フィールドが多いと、実際の表示と返されるレコードが異なる場合があることが判明しました。恐ろしいですね(汗
Dispatcher を使ってみる
この現象、どうやらレコードやフィールドが多すぎるか、ビューが複雑だと、フィルタリングと要素の描画更新のタイミングがずれるため発生するように思えます。そこで Dispatcher を使い、要素の描画とレコードの取得を同期するようタイミングを調整してみました。
これで、表示されてるレコード数とプログラム内で処理するレコード数の同期は取れました、ただし、状況により恐ろしい事態が発生します。フィルターのテキストボックスに文字列打ち込んでると、たまに
別のユニットが既に開いている間は、undo ユニットを再度開くことはできません。
と、InvalidOperationException 例外を吐いて、アプリケーションがクラッシュします。.NET Framework のソースコード追っかけると、UndoManager の Reopen メソッドで例外起こしてるのですが、恐ろしいですね。危険極まりないので、やみくもに Dispatcher を使うのは止めましょうw
RecordFilter.ApplyPendingFilter メソッド
そこで散々調べた結果*1、RecordFilter.ApplyPendingFilter メソッドを使えば、安全にフィルターの変更をビューに適用できることが判りました。以下、修正したコードです。
RecordFilter.ApplyPendingFilter の解説を読むと、
フィルターの保留中の変更を適用します。
としか書いてないしネットの情報も殆どないので、何のこっちゃ?と思ってたのですが、今回初めて使ってみました。果たしてこれが本来の使用方法かどうか怪しいのですが、とりあえず正常動作してるので、まあ良しといたしましょう(汗