如何在编辑DataGridViewTextBoxColumn并按EnterKey后阻止进入下一行?

我正在使用DataGridViews编写程序。 在一个DatagridView有一个DataGridViewTextBoxColumn ,可以由用户编辑。 当用户完成键入数字时,他按下键盘上的ENTER。 现在DataGridView完成所有Events ,在所有Events ,最后一件事就是问题。

一切都完成了,Windows将选择下一个DataGridViewRow ,我无法阻止这一点。

我试过了

 if (e.KeyData == Keys.Enter) e.SuppressKeyPress = true; // or e.Handled 

在我发现的几乎所有事件中。 遗憾的是,当DataGridViewTextBoxColumn未处于编辑模式时,我只能阻止ENTER键。

在编辑中,我的方法是找到ENTER

添加事件

 private void dgr_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { e.Control.KeyPress += new KeyPressEventHandler(dgr_KeyPress_NumericTester); } 

这是仅接受数字输入的事件。

 private void dgr_KeyPress_NumericTester(object sender, KeyPressEventArgs e) { if (!Char.IsDigit(e.KeyChar) && e.KeyChar != 8) e.Handled = true; } 

详细解释:

当用户输入一个有一些依赖的值时,我想给另一个控件重点,所以他用来纠正依赖。

我也尝试使用DependingControl.Focus()但最后一次“输入”将是视图中的最后一件事。

有人知道如何防止这种情况吗?

好吧,我设法得到了一些可以做你想要的东西(或者至少做了很难的部分,我认为你已经完成了大部分其他工作)但是解决方案让我的皮肤爬行了。

我最后在编辑单元格时“取消”输入键事件,以使用CellEndEdit事件和SelectionChanged事件的混合。

我介绍了几个存储某些状态的类级别字段 – 特别是在编辑单元格结束时我们所处的行以及是否正在停止更改选择。

代码如下所示:

 public partial class Form1 : Form { private int currentRow; private bool resetRow = false; public Form1() { InitializeComponent(); // deleted out all the binding code of the grid to focus on the interesting stuff dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit); // Use the DataBindingComplete event to attack the SelectionChanged, // avoiding infinite loops and other nastiness. dataGridView1.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(dataGridView1_DataBindingComplete); } void dataGridView1_SelectionChanged(object sender, EventArgs e) { if (resetRow) { resetRow = false; dataGridView1.CurrentCell = dataGridView1.Rows[currentRow].Cells[0]; } } void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { resetRow = true; currentRow = e.RowIndex; } void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) { dataGridView1.SelectionChanged += new EventHandler(dataGridView1_SelectionChanged); } } 

你需要彻底测试它,以确保它完全符合你的需要。 我只检查了当按下编辑控件输出时它确实停止了行更改。

就像我说的那样 – 我不太高兴需要做这样的事情 – 它感觉非常脆弱,而且它可能会产生奇怪的副作用。 但是,如果你必须有这种行为,并且你测试得好,我认为这是你想要的唯一方法。

我尝试通过从Textbox列inheritancecustomcolumn并覆盖以下事件来更改Grid的Enter行为

 protected override bool ProcessDialogKey(Keys keyData) { if (keyData == Keys.Enter) return base.ProcessDialogKey(Keys.Tab); else return base.ProcessDialogKey(keyData); } 

因此,不是发送Enter键而是模拟Tab的动作,它将移动到下一个单元格。 希望这可以帮助

 Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown If e.KeyData = Keys.Enter Then e.Handled = True End Sub 

这只是一种解决方法,而不是一个真正的解决方案,但它确实有效。

我知道这个问题很久以前就被问过了,但对于那些希望将来搜索我的人来说,答案可能会有用。 最好的解决方案是使用自定义列和文本框,因为我们将利用内置类

 class Native { public const uint WM_KEYDOWN = 0x100; [DllImport("user32.dll")] public static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam); } //the column that will be added to dgv public class CustomTextBoxColumn : DataGridViewColumn { public CustomTextBoxColumn() : base(new CustomTextCell()) { } public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { if (value != null && !value.GetType().IsAssignableFrom(typeof(CustomTextCell))) { throw new InvalidCastException("Must be a CustomTextCell"); } base.CellTemplate = value; } } } //the cell used in the previous column public class CustomTextCell : DataGridViewTextBoxCell { public override Type EditType { get { return typeof(CustomTextBoxEditingControl); } } } //the edit control that will take data from user public class CustomTextBoxEditingControl : DataGridViewTextBoxEditingControl { protected override void WndProc(ref Message m) { //we need to handle the keydown event if (m.Msg == Native.WM_KEYDOWN) { if((ModifierKeys&Keys.Shift)==0)//make sure that user isn't entering new line in case of warping is set to true { Keys key=(Keys)m.WParam; if (key == Keys.Enter) { if (this.EditingControlDataGridView != null) { if(this.EditingControlDataGridView.IsHandleCreated) { //sent message to parent dvg Native.PostMessage(this.EditingControlDataGridView.Handle, (uint)m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32()); m.Result = IntPtr.Zero; } return; } } } } base.WndProc(ref m); } } 

然后我们来到dgv本身我使用了一个从DataGridView派生的新类并添加了我的列并处理了来自wndproc的回车键

 void Initialize() { CustomTextBoxColumn colText = new CustomTextBoxColumn(); colText.DataPropertyName = colText.Name = columnTextName; colText.HeaderText = columnTextAlias; colText.DefaultCellStyle.WrapMode = DataGridViewTriState.True; this.Columns.Add(colText); DataGridViewTextBoxColumn colText2 = new DataGridViewTextBoxColumn(); colText2.DataPropertyName = colText2.Name = columnText2Name; colText2.HeaderText = columnText2Alias; colText2.DefaultCellStyle.WrapMode = DataGridViewTriState.False; this.Columns.Add(colText2); } protected override void WndProc(ref Message m) { //the enter key is sent by edit control if (m.Msg == Native.WM_KEYDOWN) { if ((ModifierKeys & Keys.Shift) == 0) { Keys key = (Keys)m.WParam; if (key == Keys.Enter) { MoveToNextCell(); m.Result = IntPtr.Zero; return; } } } base.WndProc(ref m); } //move the focus to the next cell in same row or to the first cell in next row then begin editing public void MoveToNextCell() { int CurrentColumn, CurrentRow; CurrentColumn = this.CurrentCell.ColumnIndex; CurrentRow = this.CurrentCell.RowIndex; if (CurrentColumn == this.Columns.Count - 1 && CurrentRow != this.Rows.Count - 1) { this.CurrentCell = Rows[CurrentRow + 1].Cells[1];//0 index is for No and readonly this.BeginEdit(false); } else if(CurrentRow != this.Rows.Count - 1) { base.ProcessDataGridViewKey(new KeyEventArgs(Keys.Tab)); this.BeginEdit(false); } } 

你可以简单地做到….

1 …为该网格视图创建KeyDown事件。(转到gridview上的属性并双击KeyDown事件)。

2 …过去这段代码 –

 if(e.KeyData == Keys.Enter) { e.Handled = true; } 

3 ……最后看起来像这样。

 private void dgvSearchResults_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Enter) { e.Handled = true; } } 

4 ..运行程序,看看。

这个答案真的来晚了……

但我有完全相同的问题,并不想缓存行等。所以我google了,这是我的问题的解决方案。 致于如何防止Enter键按下结束DataGridView中的EditMode?

从DataGridViewinheritance并添加此代码(vb.net):

 Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean If Commons.Options.RowWiseNavigation AndAlso Me.IsCurrentCellInEditMode AndAlso (keyData = Keys.Enter Or keyData = Keys.Tab) Then ' End EditMode, then raise event, so the standard-handler can run and the refocus is being done Me.EndEdit() OnKeyDown(New KeyEventArgs(keyData)) Return True End If 'Default Return MyBase.ProcessCmdKey(msg, keyData) End Function 

简单地说它会正常工作。

 private void dataGridViewX1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { SendKeys.Send("{UP}"); SendKeys.Send("{Right}"); } 

如果您只需要在输入时关闭表单,则可以使用以下代码。 我认为网格是只读的,你不需要区分按下输入的情况。

 public class DataGridViewNoEnter : DataGridView { protected override bool ProcessDataGridViewKey(KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { ((Form)this.TopLevelControl).DialogResult = DialogResult.OK; return false; } return base.ProcessDataGridViewKey(e); } }