MW211 EXIT

devlog
C#/DataGridViewで編集中に矢印キーで隣に行かせない
2019年02月10日
DataGridViewで編集中に、先頭で左もしくは末尾で右の矢印キーを押すと
隣のセルに移動していまうという現象がある。
Excelの場合はそうはならないので、C#でもそのようにしようと思ったが
結構苦労した(解決できたがそれがベストプラクティスかもわからない)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【非編集中のみの制限】
┌──────────────────────────────────────┐
│private void データグリッドビュー_KeyDown(object sender, KeyEventArgs e)    │
│{                                                                           │
│    if ((e.KeyCode == Keys.Right) || (e.KeyData == Keys.Left)) {            │
│        e.Handled = true;                                                   │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
まず、データグリッドビュー本体のKeyDownイベントで制限をかけてみたが
まったく矢印キーを受け付けなくなってしまった。
しかも、マウスを使って編集中にして試してみたら本題の部分が筒抜けだった。
これは、まったくの逆効果だ。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【編集中のみの制限】
┌──────────────────────────────────────┐
│private void データグリッドビュー_EditingControlShowing(                    │
│    object sender, DataGridViewEditingControlShowingEventArgs e)            │
│{                                                                           │
│    if (e.Control is DataGridViewTextBoxEditingControl) {                   │
│        DataGridViewTextBoxEditingControl テキストボックス                  │
│            = (DataGridViewTextBoxEditingControl)e.Control;                 │
│        テキストボックス.KeyDown -= new KeyEventHandler(自作イベント);      │
│        テキストボックス.KeyDown += new KeyEventHandler(自作イベント);      │
│    }                                                                       │
│}                                                                           │
│──────────────────────────────────────│
│private void 自作イベント(object sender, KeyEventArgs e)                    │
│{                                                                           │
│    if ((e.KeyCode == Keys.Right) || (e.KeyData == Keys.Left)) {            │
│        //e.Handled = true;                                                 │
│        e.SuppressKeyPress = true;                                          │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
次に、編集中(テキストボックス)のKeyDownイベントで制限をかけてみた。
こちらは、子テキストボックスのイベントを自作する感じなのだが
これだと、編集中はまったく矢印キーを受け付けなくなってしまった反面
こちらも本題の部分が筒抜けだった。
こちらも一つ前のと互角の逆効果バージョンだ。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【セルを移動させない】
┌──────────────────────────────────────┐
│private void データグリッドビュー_CellValidating(                           │
│    object sender, DataGridViewCellValidatingEventArgs e)                   │
│{                                                                           │
│    e.Cancel = true;                                                        │
│}                                                                           │
└──────────────────────────────────────┘
で、どうも調べてみると、本題の場合、KeyDownイベントの前に
編集中イベントは解散してるっぽいことがわかった。
つまり、編集中に末尾で右矢印キーを押すと、
PreviewKeyDownイベントは反応するのに、KeyDownイベントはまったく反応しないのだ。
ということで、編集後の方で制御できないものかと方針を変更。
セルが移動した時に(移動しそうになった時に)それを禁止する方法を検証。
これだとまったく制御不能でどうしようもないが、検討的には大きな前進だ。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
【編集中から非編集中に変わる直前での制限】
┌──────────────────────────────────────┐
│private bool mIsセル移動禁止;                                               │
├──────────────────────────────────────┤
│public コンストラクタ()                                                     │
│{                                                                           │
│    mIsセル移動禁止 = false;                                                │
│}                                                                           │
├──────────────────────────────────────┤
│private void データグリッドビュー_CellValidating(                           │
│    object sender, DataGridViewCellValidatingEventArgs e)                   │
│{                                                                           │
│    if (mIsセル移動禁止) {                                                  │
│        e.Cancel = true;                                                    │
│    }                                                                       │
│}                                                                           │
├──────────────────────────────────────┤
│private void データグリッドビュー_EditingControlShowing(                    │
│    object sender, DataGridViewEditingControlShowingEventArgs e)            │
│{                                                                           │
│    if (e.Control is DataGridViewTextBoxEditingControl) {                   │
│        DataGridViewTextBoxEditingControl テキストボックス                  │
│            = (DataGridViewTextBoxEditingControl)e.Control;                 │
│        テキストボックス.PreviewKeyDown                                     │
│            -= new PreviewKeyDownEventHandler(自作イベント);                │
│        テキストボックス.PreviewKeyDown                                     │
│            += new PreviewKeyDownEventHandler(自作イベント);                │
│    }                                                                       │
│}                                                                           │
├──────────────────────────────────────┤
│private void 自作イベント(object sender, PreviewKeyDownEventArgs e)         │
│{                                                                           │
│    mIsセル移動禁止 = false;                                                │
│    if ((e.KeyCode == Keys.Right) || (e.KeyData == Keys.Left)) {            │
│        mIsセル移動禁止 = true;                                             │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
ということで、完成。
自作イベントをPreviewKeyDown側に設置し、編集中の矢印キー押下を認識。
それをメンバ変数で伝達し、さきほどのセル移動させない処理にて
その制限を限定することにより、思った通りの動作となった。
分類:VC#