.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
disable the default Enter/Return key behavior in a datagridview
提问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
另一种选择是创建自定义网格视图控件
回答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 = true在DataGridView.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()回报true的Keys.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

