如何防止在编辑DataGridViewTextBoxColumn并按EnterKey后转到下一行

本文关键字:一行 何防止 编辑 DataGridViewTextBoxColumn EnterKey 并按 | 更新日期: 2023-09-27 17:52:35

我正在用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()中尝试过,但最后一个"回车"将是视图中的最后一个。

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

如何防止在编辑DataGridViewTextBoxColumn并按EnterKey后转到下一行

我尝试通过继承来自文本框列并覆盖以下事件

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

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

好吧,我设法做了一些你想做的事情(或者至少做了最难的部分,我想你已经做了大部分其他事情(,但这个解决方案让我毛骨悚然。

在编辑单元格时,我最终"取消"了回车键事件,以便混合使用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);
    }
} 

你需要对它进行彻底的测试,以确保它能满足你的需求。我只是检查了一下,当在编辑控件外按enter键时,它确实会停止行更改。

正如我所说——我对需要做这样的事情不太满意——它感觉很脆,而且可能会有奇怪的副作用。但如果你必须有这种行为,并且你测试得很好,我认为这是做你想做的事的唯一方法。

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

这只是一个变通办法,不是一个真正的解决方案,但它是有效的。

您可以简单地完成

1…为该网格视图创建KeyDown事件。(转到网格视图上的属性,然后双击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.运行程序并查看。

这个答案来得真晚。。。

但我遇到了完全相同的问题,不想缓存行等。所以我在谷歌上搜索了一下,这就是我对这个问题的解决方案。如何防止Enter键在DataGridView中结束EditMode?

从DataGridView继承并添加以下代码(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

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

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);
    }
}

只要这样做,它就会正常工作。

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

基于这个解决方案,我创建了自己的解决方案。您不需要在DataGrid上为Enter_key捕获KeyDown_Event,而是切换AllowUserToAddRows属性。在我的情况下,我选择了CellContentDoubleClick来启用它:

private void myDataGrid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) {
    myDataGrid.AllowUserToAddRows = false;
}
private void myDataGrid_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e) {
    myDataGrid.AllowUserToAddRows = true;
}

我找到的唯一方法是创建一个自定义DataGridView。

编辑:这将更改箭头键的默认行为,并允许在编辑中使用箭头键。您可以更改此删除";e.KeyCode==键.左||e.KeyCode===键.右"。

    public class CustomDataGridview : DataGridView
    {
        protected override bool ProcessDataGridViewKey(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
            {
                return false;
                //if (IsCurrentCellInEditMode)   // disable the keys only in EditMode
                //{
                //    return false;
                //}
            }
            return base.ProcessDataGridViewKey(e);
        }
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Enter)
            {
                EndEdit();
                return true;
            }
            return base.ProcessDialogKey(keyData);
        }
    }
    CustomDataGridview dgvCustom = new CustomDataGridview();
    DataGridViewTextBoxColumn InputFile2 = new DataGridViewTextBoxColumn();
    DataGridViewTextBoxColumn OutputFile2 = new DataGridViewTextBoxColumn();
    DataGridViewComboBoxColumn Format2 = new DataGridViewComboBoxColumn();
    DataGridViewTextBoxColumn Options2 = new DataGridViewTextBoxColumn();
    private void SetupDataGridView()
    {
        //All your DataGridView settings
    }
    public Form1()
    {
        InitializeComponent();
        SetupDataGridView();
    }

如果您只需要在回车时关闭表单,您可以使用以下代码。我想网格是只读的,你不需要区分回车键被按下的情况。

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);
    }      
}