DataGridViewのComboBoxでフィルタ

DataGridViewのComboBoxで行の内容によって中身をフィルタリングしたいことってありますよね
これが意外と情報が無いんですよね… そんなわけで試行錯誤したらなんとか出来ました。

最初に行ったのはOnEditingControlShowingメソッドでコンボ列に作成される
DataGridViewComboBoxEditingControlクラスのDataSource(DataView)に設定してフィルタする方法。
(クラス名なげぇ)
残念ながらこちらの方法では既存選択項目の内容がフィルタで消えたりしてエラーが起きました。
あとは新規行でコンボを開くとなぜか黒背景で潰れていたり…(描画関係の.NETのバグ?)

その後ふと思いついたことが、データバインド出来る単位で列単位だけだっけ?…という事

早速調べると…あるじゃないですか!セル単位が!

DataSource プロパティを変更すると、セルの Items コレクションが再初期化され、セルが自動的に再描画されます。

DataSource プロパティの値を変更すると、コントロールは、ValueMember プロパティの値と DisplayMember プロパティの値を、新しいデータ ソースに適用しようとします。新しいデータ ソースに対応する値が存在しない場合は、各プロパティを null 参照 (Visual Basic では Nothing) に設定します。 このプロセスで発生する例外は無視されます。ただし、重要な例外 (NullReferenceExceptionStackOverflowExceptionOutOfMemoryExceptionThreadAbortExceptionExecutionEngineExceptionIndexOutOfRangeException、または AccessViolationException) のうちいずれかが発生した場合を除きます。

しかも再設定しても元の値を認識する的なことが書いてありますね。

VB.NETですが、こんな感じのコードで動作確認OKです。
両方書ける方ならC#への読み替えも余裕でしょう。
(※ロジックを示すだけのサンプルです。そのままだと動きません)

これが正解かは正直なところ分かりませんが、

CellBeginEditイベントで対象行の特定コンボを編集開始しようとしているかをチェックして
対象セルであれば元のDataTableからDataViewを新しく作ってRowFilterを設定しています。
(以後は新規作成したDataViewを使い回し)
安全のために元々ある行のRowFilterには選択しているコードを条件につけています

元のデータソースはDataTableである必要があります。

コメントを残す

メールアドレスが公開されることはありません。