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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1887299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:39:43  来源:igfitidea点击:

disable the default Enter/Return key behavior in a datagridview

.netvb.netwinformsdatagridview

提问by Ramji

In vb.net datagridview the default Enter/Return key behavior is to move to the next row is there a quick and easy way to avoid that.

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

Any suggestions are welcome

欢迎任何建议

回答by Adriaan Stander

You can try something like this in the gridview key down event

您可以在 gridview key down 事件中尝试这样的操作

Private Sub DataGridView1_Keydown (...) Handlers DataGridView1.KeyDown
   If e.KeyCode = Keys.Enter Then
       ' Your code here
       e.SuppressKeyPress = True
  End If 
End Sub

Another option would be to create a custom grid view control

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

DataGridView.ProcessDataGridViewKey Method

DataGridView.ProcessDataGridViewKey 方法

回答by Burimi

You can just use keyPress event:

您可以只使用 keyPress 事件:

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

回答by binki

I myself, when disabling the Enter key's default behavior on a DataGridView, want to be able to achieve a similar effect to setting DataGridView.StandardTabto true. Enabling StandardTabenables the user to more easily navigate between different controls in a form. This makes it behave more like a ListBox, especially if the DataGridViewonly has one column. The default behavior of of the Enter key and the behavior which I would expect from setting a (nonexistent) DataGridView.StandardEnterkey to truewould be to send the key event to containing controls, probably resulting in the Form.AcceptButtonbeing activated. The proposed methods of setting KeyEventArgs.SuppressKeyPress = truein DataGridView.KeyDownor not even firing DataGridView.KeyDownwhen the input key is Enterdo not enable “standard” Enter key behavior; these methods instead let the Enter key event get swallowed.

我自己,当在 a 上禁用 Enter 键的默认行为时DataGridView,希望能够达到与设置DataGridView.StandardTab为类似的效果true。启用StandardTab使用户能够更轻松地在表单中的不同控件之间导航。这使得它的行为更像 a ListBox,尤其是当它DataGridView只有一列时。Enter 键的默认行为以及我期望将(不存在的)DataGridView.StandardEnter键设置为true将键事件发送到包含控件的行为,可能会导致Form.AcceptButton被激活。所提出的方法设置KeyEventArgs.SuppressKeyPress = trueDataGridView.KeyDown连射击DataGridView.KeyDown在输入键是输入不要启用“标准”回车键行为;这些方法反而让 Enter 键事件被吞没。

The following shows how I have managed to get “Standard” Enter key behavior (including invoking AcceptButtonappropriately) out of a DataGridView. It is ugly because I do not know a better way to run the logic in Control.ProcessDialogKey()(which is just to call the Parent (the container)'s ProcessDialogKey()or return falseif there is no Parent) than to copy it into my own derived class. (I essentially need to use the invalid/impossible base.base.ProcessDialogKey()syntaxto work around System.Windows.Forms's non-extensibility in a cleaner manner). Because of this, I am forced to use reflection to access the protected Control.ProcessDialogKey()method of the parent (the container) Controlobject when it exists.

下面显示了我如何设法AcceptButton从 DataGridView 中获得“标准”输入键行为(包括正确调用)。这很丑陋,因为我不知道比将其复制到我自己的派生类中更好的方法来运行逻辑Control.ProcessDialogKey()(这只是调用父(容器)ProcessDialogKey()false在没有父时返回)。(我基本上需要使用无效/不可能的base.base.ProcessDialogKey()语法System.Windows.Forms更清晰的方式解决的不可扩展性问题)。因此,Control.ProcessDialogKey()当父(容器)Control对象存在时,我被迫使用反射来访问其受保护的方法。

DataGridVew.IsInputKey()returns truefor Keys.Enter. This enables it to see the Enter key in its DataGridView.OnKeyDown()method where it eventually calls DataGridView.ProcessEnterKey()which reacts to the Enter key in different ways based on the setting of DataGridView.EditMode. But this also disables sending the key event to ProcessDialogKey()from where normal controls would bubble the Enter key event to their Parents (enabling AcceptButtonto work, for example). Thus, we revert this behavior by overriding IsInputKey()and now DataGridView.ProcessDialogKey()will get called when Enter is pressed.

DataGridVew.IsInputKey()回报trueKeys.Enter。这使它能够在其DataGridView.OnKeyDown()最终调用的方法中看到 Enter 键,该方法DataGridView.ProcessEnterKey()根据 的设置以不同的方式对 Enter 键做出反应DataGridView.EditMode。但这也禁止将键事件发送到ProcessDialogKey()普通控件会将 Enter 键事件冒泡到其父级的位置(AcceptButton例如,允许工作)。因此,我们通过覆盖来恢复此行为IsInputKey(),现在DataGridView.ProcessDialogKey()将在按下 Enter 时被调用。

But that is not enough. DataGridView.ProcessDialogKey()has a hardcoded call to DataGridView.ProcessEnterKey()and only calls its base Control.ProcessDialogKey()if ProcessEnterKey()returns false. At this point, it would seem common sense to override ProcessEnterKey()with something that would just return falsewhen we want standard Enter key behavior. But, alas, it is a non-virtual method. Thus, we are forced to override something we can override, DataGridView.ProcessDialogKey(), and reimplement it while skipping the call to ProcessEnterKey(). This is where we are also unable to directly call Control.ProcessDialogKey()and are forced to use reflection to call the parent/container object's ProcessDialogKey()method. But once we successfully make that call, we finally have standard Enter behavior and AcceptButtonis accessible even while the DataGridViewhas focus!

但这还不够。DataGridView.ProcessDialogKey()有一个硬编码的调用,DataGridView.ProcessEnterKey()并且只有Control.ProcessDialogKey()ProcessEnterKey()返回 false时才调用它的基础。在这一点上,当我们想要标准的 Enter 键行为时,覆盖ProcessEnterKey()一些只会返回的东西似乎是常识false。但是,唉,这是一种非虚拟方法。因此,我们被迫覆盖一些我们可以覆盖的东西DataGridView.ProcessDialogKey(),并在跳过对 的调用的同时重新实现它ProcessEnterKey()。这也是我们无法直接调用的地方Control.ProcessDialogKey(),被迫使用反射来调用父/容器对象的ProcessDialogKey()方法。但是一旦我们成功地进行了调用,我们最终就拥有了标准的 Enter 行为,并且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);
    }
}

回答by slugster

Override the DataGridView (write your own that inherits from it), and process the OnKeyDownmethod.

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

回答by CrazyIvan1974

The accepted solution did not work for me. The code below DID. From http://www.vbforums.com/showthread.php?603242-Block-enter-key-in-datagridview-in-vb-net: (original source unknown)

接受的解决方案对我不起作用。下面的代码 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