禁用datagridview中的默认Enter / Return键行为

时间:2009-12-11 10:53:21

标签: .net vb.net winforms datagridview

在vb.net datagridview中,默认的Enter / Return键行为是移动到下一行,有一种快速简便的方法可以避免这种情况。

欢迎任何建议

6 个答案:

答案 0 :(得分:28)

您可以在gridview按键事件

中尝试这样的操作
Private Sub DataGridView1_Keydown (...) Handlers DataGridView1.KeyDown
   If e.KeyCode = Keys.Enter Then
       ' Your code here
       e.SuppressKeyPress = True
  End If 
End Sub

另一种选择是创建自定义网格视图控件

DataGridView.ProcessDataGridViewKey Method

答案 1 :(得分:3)

我自己,当在DataGridView上禁用Enter键的默认行为时,希望能够达到将DataGridView.StandardTab设置为true的类似效果。启用StandardTab使用户可以更轻松地在表单中的不同控件之间导航。这使得它更像ListBox,特别是如果DataGridView只有一列。 Enter键的默认行为以及将(不存在的)DataGridView.StandardEnter键设置为true时所期望的行为是将键事件发送到包含控件,可能导致{{ 3}}被激活。 Form.AcceptButtonsetting KeyEventArgs.SuppressKeyPress = true in DataGridView.KeyDown的建议方法不启用“标准”输入密钥行为;这些方法改为吞下Enter键事件。

以下显示了我如何设法获得“标准”从DataGridView输入关键行为(包括适当地调用AcceptButton)。这很难看,因为我不知道在Control.ProcessDialogKey()中运行逻辑的更好方法(只是调用父(容器)的ProcessDialogKey()或返回false如果有的话没有父母)而不是将其复制到我自己的派生类中。 (我基本上需要使用not even firing DataGridView.KeyDown when the input key is Enter以更清晰的方式解决System.Windows.Forms的不可扩展性问题。因此,我被迫使用反射来访问父(容器)Control.ProcessDialogKey()对象的受保护Control方法。

DataGridVew.IsInputKey()会为true返回Keys.Enter。这使它能够在DataGridView.OnKeyDown()方法中看到Enter键,最终调用invalid/impossible base.base.ProcessDialogKey() syntax,根据DataGridView.ProcessEnterKey()的设置,它以不同的方式对Enter键作出反应。但是这也会禁用将关键事件发送到ProcessDialogKey(),正常控件会将Enter键事件冒泡到其父级(例如,启用AcceptButton)。因此,我们通过覆盖IsInputKey()来恢复此行为,现在DataGridView.ProcessDialogKey()将在按下Enter时被调用。

但这还不够。 DataGridView.ProcessDialogKey()DataGridView.ProcessEnterKey()进行了硬编码调用,只有Control.ProcessDialogKey()返回false才会调用其基数ProcessEnterKey()。在这一点上,当我们想要标准的Enter键行为时,用ProcessEnterKey()覆盖false来覆盖DataGridView.ProcessDialogKey()似乎是常识。但是,唉,这是一种非虚拟方法。因此,我们被迫覆盖我们可以覆盖的内容ProcessEnterKey(),并在跳过对Control.ProcessDialogKey()的调用时重新实现它。这是我们也无法直接调用ProcessDialogKey()并被迫使用反射来调用父/容器对象的AcceptButton方法的地方。但是,一旦我们成功拨打该电话,我们最终会有标准的输入行为,即使DataGridView有焦点,也可以访问/// <summary> /// A DataGridView with a StandardEnter property which behaves /// like StandardTab. /// </summary> class StandardEnterDataGridView : DataGridView { /// <summary> /// Like StandardTab but for the Enter key. /// </summary> [Category("Behavior"), Description("Disable default edit/advance to next row behavior of of the Enter key.")] public bool StandardEnter { get; set; } /// <summary> /// Implement StandardEnter. /// </summary> protected override bool IsInputKey(Keys keyData) { if (StandardEnter && keyData == Keys.Enter) // Force this key to be treated like something to pass // to ProcessDialogKey() (like the Enter key normally // would be for controls which aren’t DataGridView). return false; return base.IsInputKey(keyData); } private static MethodInfo _Control_ProcessDialogKey = typeof(Control).GetMethod("ProcessDialogKey", BindingFlags.Instance|BindingFlags.NonPublic); protected override bool ProcessDialogKey(Keys keyData) { if (StandardEnter && keyData == Keys.Enter) // Copy the default implementation of // Control.ProcessDialogKey(). Since we can’t access // the base class (DataGridView)’s base class’s // implementation directly, and since we cannot // legally access Control.ProcessDialogKey() on other // Control object, we are forced to use reflection. return Parent == null ? false : (bool)_Control_ProcessDialogKey.Invoke(Parent, new object[] {keyData, }); return base.ProcessDialogKey(keyData); } }

{{1}}

答案 2 :(得分:2)

您可以使用keyPress事件:

 private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                //You're Code
            }
            e.Handled = true;
            return;
        }

答案 3 :(得分:1)

覆盖DataGridView(编写自己继承的DataGridView),并处理 OnKeyDown 方法。

public partial class UserControl1 : DataGridView
{
    public UserControl1()
    {
        InitializeComponent();
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
            return;

        base.OnKeyDown(e);
    }
}

答案 4 :(得分:1)

我添加这个脚注是因为我对这篇文章非常感兴趣,因为它与我在 DataGridView 中遇到的一个不同的问题很接近。这是因为 Enter 键会将您带到下面的单元格,从而阻止用户对单元格中的文本进行简单编辑。重写了这个类并花了很多时间,我终于找到了以下文章: Use Enter to add new line in datagridview cell

如果这是您唯一的问题,那么了解 SHIFT+ENTER 的工作原理(尽管不直观),可能会为您节省大量时间!想我只会在表单中添加一个标签来提醒用户。

答案 5 :(得分:0)

接受的解决方案对我不起作用。 DID下面的代码。来自http://www.vbforums.com/showthread.php?603242-Block-enter-key-in-datagridview-in-vb-net :(原始来源未知)

Public Class clsDataGridView
Inherits System.Windows.Forms.DataGridView

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean

    If keyData = Keys.Return Or keyData = Keys.Tab Then
        If CurrentCellAddress.X = ColumnCount - 1 Then
            keyData = Keys.Cancel
            With msg
                .WParam = CType(Keys.Cancel, IntPtr)
            End With
        Else
            keyData = Keys.Tab
            With msg
                .WParam = CType(Keys.Tab, IntPtr)
            End With
        End If
    End If

    If keyData = (Keys.Shift Or Keys.Tab) Then
        If CurrentCellAddress.X = 0 Then
            keyData = Keys.Cancel
            With msg
                .WParam = CType(Keys.Cancel, IntPtr)
            End With
        End If
    End If
    Return MyBase.ProcessCmdKey(msg, keyData)

End Function

Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean

    If keyData = Keys.Return Or keyData = Keys.Tab Then
        If CurrentCellAddress.X = ColumnCount - 1 Then
            keyData = Keys.Cancel
        Else
            keyData = Keys.Tab
        End If
    End If

    If keyData = (Keys.Shift Or Keys.Tab) Then
        If CurrentCellAddress.X = 0 Then
            keyData = Keys.Cancel
        End If
    End If
    Return MyBase.ProcessDialogKey(keyData)

End Function

End Class