DataGridViewでEnterキーを押すと隣のセルにフォーカスが移動されるようにする を拡張し、隣だけではなく任意のセルにフォーカスが移動できるようにしてみました。
考え方は、次の通りです。
- DataGridView のサブクラスを作成し、ProcessDialogKey メソッドと ProcessDataGridViewKey メソッドを再定義します。隣のセルに移動 では ProcessTabKey でフォーカスを隣のセルに移動させています。ここでは、フォーカス移動ではなく、イベントを発生させます。
- エンターキーが押されたときに呼び出されるイベントハンドラで、フォーカスが移動するセルを BeginInvoke で設定します。
Enter キーが押されたときにイベント EnterKeyPressed を発生させるように拡張したクラスは、次のようになります。
/// <summary> /// Enter キーが押されたときにイベントを発生させるように拡張した /// <see cref="DataGridView"/> クラス。 /// </summary> public class MyDataGridView : DataGridView { // DataGridView で Enter キーが押されたときに発生させるイベント。 public event EventHandler EnterKeyPressed; // 以下のプログラムの基本部分は、 // "DataGridViewでEnterキーを押すと隣のセルにフォーカスが移動されるようにする" // (https://dobon.net/vb/dotnet/datagridview/enterkeymoveright.html) から // 使わせていただきました。 [System.Security.Permissions.UIPermission( System.Security.Permissions.SecurityAction.Demand, Window = System.Security.Permissions.UIPermissionWindow.AllWindows)] protected override bool ProcessDialogKey(Keys keyData) { // Enterキーが押された時は、EnterKeyPressed イベントを発生させる。 if ((keyData & Keys.KeyCode) == Keys.Enter) { EnterKeyPressed?.Invoke(this, EventArgs.Empty); } return base.ProcessDialogKey(keyData); } [System.Security.Permissions.SecurityPermission( System.Security.Permissions.SecurityAction.Demand, Flags = System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)] protected override bool ProcessDataGridViewKey(KeyEventArgs e) { // Enterキーが押された時は、EnterKeyPressed イベントを発生させる。 if (e.KeyCode == Keys.Enter) { EnterKeyPressed?.Invoke(this, EventArgs.Empty); } return base.ProcessDataGridViewKey(e); } }
フォームがロードされたとき、拡張した DataGridView をフォームに追加し設定を行う部分を、次に示します。
private void Form1_Load(object sender, EventArgs e) { // MyDataGridView をフォームに追加する。 MyDataGridView myDgv = new MyDataGridView(); Controls.Add(myDgv); // 追加した MyDataGridView をフォーム全体に表示し、列と行を追加する。 myDgv.Dock = DockStyle.Fill; myDgv.Columns.Add("column1", "列 1"); myDgv.Columns.Add("column2", "列 2"); myDgv.Columns.Add("column3", "列 3"); myDgv.Rows.Add(); // Enter キーが押されたら MyDgvEnterKeyPressed を呼び出す。 myDgv.EnterKeyPressed += MyDgvEnterKeyPressed; }
Enter キーが押されたときに呼び出されるイベントハンドラです。BeginInvoke で指定した内容は、呼ばれた時点ですぐに実行されるのではなく、この一連の処理のあと実行されることになります。この呼び出しに続く処理で、フォーカスはどこか別のセルに移動されるかもしれません。しかし、その後で実行される BeginInvoke のアクションにより、ここで設定した位置にさらに移動します。
private void MyDgvEnterKeyPressed(object sender, EventArgs e) { // CurrentCell が設定されておらず null なら、そのまま戻る。 MyDataGridView myDgv = (MyDataGridView)sender; DataGridViewCell currCell = myDgv.CurrentCell; if (currCell == null) { return; } // 次にフォーカスが移動するセルを決める。ここでは右斜め下に移動させる。 int nextColumnIndex = (currCell.ColumnIndex + 1) % myDgv.ColumnCount; int nextRowIndex = (currCell.RowIndex + 1) % myDgv.RowCount; DataGridViewCell nextCell = myDgv[nextColumnIndex, nextRowIndex]; // 次に移動するセルを BeginInvoke() で設定する。 Action setCurrentCellAction = new Action(() => myDgv.CurrentCell = nextCell); BeginInvoke(setCurrentCellAction); }