Bypass read only cells in DataGridView when pressing TAB key

匿名 (未验证) 提交于 2019-12-03 02:06:01

问题:

Can anyone show me some code of how I could bypass read only cells in DatagridView when pressing TAB key?

回答1:

Overriding the SelectionChanged event is the right approach. The property CurrentCell can be used to set the current cell. You want something like this:

private void dataGridView_SelectionChanged(object sender, EventArgs e) {     DataGridViewCell currentCell = dataGridView.CurrentCell;     if (currentCell != null)     {         int nextRow = currentCell.RowIndex;         int nextCol = currentCell.ColumnIndex + 1;         if (nextCol == dataGridView.ColumnCount)         {             nextCol = 0;             nextRow++;         }         if (nextRow == dataGridView.RowCount)         {             nextRow = 0;         }         DataGridViewCell nextCell = dataGridView.Rows[nextRow].Cells[nextCol];         if (nextCell != null && nextCell.Visible)         {             dataGridView.CurrentCell = nextCell;         }     } } 

You'll need to add a test for the current cell being read only and loop while the next cell is invisible or read only. You'll also need to check to make sure that you don't loop for ever if all cells are read only.

You'll have to cope with the case where the display index is different to the base index too.

To get this behaviour just when pressing Tab you'll need to add a KeyDown handler:

private void AlbumChecker_KeyDown(object sender, KeyEventArgs e) {     if (e.KeyCode == Keys.Tab)     {         SelectNextEditableCell(DataGridView dataGridView);     } } 

and put the first code in this new method.

You might want to check that the DataGridView has focus too.



回答2:

private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e) {    if (dataGridView1.CurrentRow.Cells[e.ColumnIndex].ReadOnly)     {         SendKeys.Send("{tab}");     } } 


回答3:

I did an example inheriting DataGridView class. The example works for TAB and ENTER keys so the user can quickly insert data, but can still use the mouse or the up, down, right, left keys to select the cells and copy them to an excel. It works simulating several TABs until the Grid gets to a non ReadOnly Cell. Hope it’s useful.

using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms;  namespace System.Windows.Forms {   class MyDataGridView : DataGridView   {     protected override bool ProcessDialogKey(Keys keyData)     {       if (keyData == Keys.Enter || keyData == Keys.Tab)       {         MyProcessTabKey(Keys.Tab);         return true;       }       return base.ProcessDialogKey(keyData);     }      protected override bool ProcessDataGridViewKey(KeyEventArgs e)     {       if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab)       {         MyProcessTabKey(Keys.Tab);         return true;       }       return base.ProcessDataGridViewKey(e);     }      protected bool MyProcessTabKey(Keys keyData)     {       bool retValue = base.ProcessTabKey(Keys.Tab);       while (this.CurrentCell.ReadOnly)       {         retValue = base.ProcessTabKey(Keys.Tab);       }       return retValue;     }   } } 


回答4:

Inherit DataGridView and override ProcessDialogKey (for key pressed while editing) and ProcessDataGridViewKey (for key pressed while not editing). When Tab was pressed, set CurrentCell to the next non-readonly cell.

Optionally override WndProc to filter mouse clicks on readonly cells. (See DataGridView.GetColumnDisplayRectangle to find which column was clicked).

Good source to start from here.



回答5:

When the cell is in edit mode, and you want to listen to keystroke events, you might try handling the DataGridView's EditingControlShowing event...

Private Sub myDvGrid_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles myDvGrid.EditingControlShowing     Dim c As DataGridViewTextBoxEditingControl = DirectCast(e.Control, DataGridViewTextBoxEditingControl)      RemoveHandler c.PreviewKeyDown, AddressOf edtctrlOn_PreviewKeyDown     RemoveHandler c.TextChanged, AddressOf edtctrlOn_TextChanged      AddHandler c.TextChanged, AddressOf edtctrlOn_TextChanged     AddHandler c.PreviewKeyDown, AddressOf edtctrlOn_PreviewKeyDown  End Sub 

Then, in the edtctrlOn_PreviewKeyDown event, you can bubble the arguments over to the original datagrid's PreviewKeyDown event handler.



回答6:

Hector - I hope you are still listening. Your solution is the most elegant and straightforward one I've seen in extensive searching. I've run into the suggestion to override the key events, but your suggestion to invoke base.ProcessTabKey is especially simple and it handles focus passing to the next control when you reach the end of the dgv. The one additional thing your solution needed was a check in MyProcessTabKey for the last cell of the dgv. If that cell is readonly and the user tabs in the previous cell, the while statement goes into an infinite loop. Adding the following code as the first statement in the while loop seems to solve the problem, though it does leave the last (readonly) cell the "active" cell (meaning it appears as though it's selected).

    if (this.CurrentCell.RowIndex == this.Rows.Count - 1                 && this.CurrentCell.ColumnIndex == this.Columns.Count - 1)                 { retValue = false; break; }  

I have a follow-on question. Do you or anyone else know how to make this approach work with Shift-Tab, so the dgv skips readonly cells in a backward direction as well? Since Shift and Tab are different key events, I don't know how to detect Shift-Tab in the overridden ProcessDialogKey and ProcessDataGridViewKey methods. Thanks. Steve



回答7:

You can catch Tab Key by this code in ProcessDialogKey

    Dim uKeyCode As Keys = (keyData And Keys.KeyCode)     Dim uModifiers As Keys = (keyData And Keys.Modifiers)      (uKeyCode = Keys.Return OrElse uKeyCode = Keys.Tab) AndAlso uModifiers = Keys.Shift 

And by this code in ProcessDataGridViewKey

    (e.KeyCode = Keys.Return OrElse e.KeyCode = Keys.Tab) AndAlso e.Modifiers = Keys.Shift 


回答8:

 if (e.KeyValue == 13)         {             e = new KeyEventArgs(Keys.Tab);         } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!