DataGridViewのcell編集後の確定イベント(アクション)は何が適切ですか?
C#のDataGridViewのCellにDatePickerを入れて編集可能にし、
編集が終わったタイミングでデータベースを更新するプログラムを作成中です。
この際、Cellの編集が終わったことを検知する必要がありますが、
ググるとこの辺りはノウハウがたくさんあり情報の絞り込みが難しいです。
(Leave ,CellEndEditなど。どれが正しいのか分かりにくいです。)
セルの編集が終わったことを検知するタイミングとしては
以下が思いついていますがどのアクションで処理を実装するのが良いでしょうか?
1.DatePickerで日付を選択後、Enterを入力したタイミング
2.DatePickerで日付を選択後、別のセルへ移動したタイミング
(他のフォーム部品を操作してフォーカスが喪失したときを含む)
ご教示いただきたく、よろしくお願いいたします。
--参考にされている方が大勢いるようですので、下記のコメントの内容を見易く記事にも追記します。--
・回答(回答者)
検証完了後に呼ばれるCellValidatedイベントが適当です。
またWindowsアプリの標準的な動作ではセルの編集が終了しても移動先が同じ行であればデータソースの更新は行いません。これに準拠した場合はRowValidatedとなります。
・コメント1(投稿者)
CellValidatedで試してみましたが、以下の(2)の要求が満たせなかったため、CellParsing というイベントに実装したところ、現状問題なく動作しております。CellParsing を使う場合の問題点や注意点等ありましたらご教示ください。
(1)該当セル編集後、閉じるボタン(×ボタン)を押した時、画面を閉じる前にコールされる。
(2)該当セル編集後、別の列でフィルターをかけたときにフィルター処理の前にコールされる。(エクセルのオートフィルターのような機能をつけております。)
CellValidated (1)○ (2)×
CellEndEdit (1)○ (2)×
CellParsing (1)○ (2)○
・コメント2(回答者)
DataGridViewの設計としてはCellParsingは入力値の解析と型変換をカスタマイズするイベントです。ですのでCellParsingの実行が完了するまではセルの値は変更することが可能で、途中で更新を行うのはあまり望ましくないです。フィルター前にEndEdit()を入れる等で回避できるのであれば別のイベントにしたほうが良いかと。
・コメント3(投稿者)
列のフィルター機能はDataGridViewAutoFilterColumnHeaderCellを使用しており、マウスクリックした時にEndEdit()を呼んでいます。ですが、最初にフィルターのリストが表示され、その後フィルターの項目を選択した後にCellValidatedやCellEndEditが呼ばれるため挙動がおかしくなります。(更新する行をフィルターで表示できなくすると更新処理ができない等)
できればフィルターの▽ボタンを押した瞬間に先にデータの更新処理をしたいのです。CellParsingでまだ完全にテストしていませんが、テストして問題なければ本来の用途ではないとのことですが、このままCellParsingを利用するかもしれません。何かコメント等ありましたらよろしくお願い致します。
・コメント4(投稿者)
CellParsingで問題が発生しました。
更新をキャンセルしたい場合に、CellBeginEditで記憶した値に戻せない場合があります。初期値がnullやDBNull.Valueの場合になぜか値が元に戻せなくなります。(初期値がDateTime型であれば戻せます。) これは致命的です。
CellValidatedにすると、何故かnullでも元に戻せたので、CellValidatedでの実装に変更しました。この場合、先に述べたフィルター選択時の問題がありますが、DataDridViewのMouseClickイベント内で、IsCurrentCellInEditModeがtrueの場合にForm.Validate()メソッドを呼ぶことで、一瞬フィルターリストも表示されますが、更新処理を先に処理することができました。
DataDridView.EditEnd()にするとフィルターリストが先に表示されてしまうため、Validateにしました。 とりあえずこれで進めてみます。