解决DataGridView回车后自动下移一行的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43145361/article/details/100079420

问题描述

DataGridView是一个很常用的数据控件,不仅可以用于二维数据的显示,同时还可以方便地进行编辑。一般控件越强大,往往也意味着它的结构很复杂,从而会有一些使用的问题。在DataGridView控件中,相信大多数使用者都会遇到一个问题就是:在单元格编辑后焦点会自动向下移动一格。

在网上有很多文章都提出了重写 ProcessCmdKey 来解决,并且给出了相应的代码,但是这些重写都是在窗体级完成,即写在窗体内。虽然解决了问题,但是不符合设计模式的开放封闭原则,使用起来会带来很多麻烦。

解决思路

为了解决这个问题,经研究发现 ProcessCmdKey 的传送机制是基于控件结构的遍历,即在控件上是一层一层传输,所以我们可以直接对 DataGridView 进行派生,然后在派生中重写这个方法即可。

代码实现

实现代码如下。

public class DataGridViewEx : DataGridView
{
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (IsCurrentCellInEditMode && keyData == Keys.Enter)
        {
            EndEdit();
            return true;
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }
}

使用实例

在本使用中,我们建议了一个DataGridView 的实例 dgv。然后在编辑时,判断单元格的数据是否是数字。对以下三种情况进行处理:

  • 数字字符串:则自动跳到下一行,方便用户继续编辑;
  • 空字符串:退出编辑模式,继续停留在当前单元格;
  • 其他字符串:弹出对话框报错,然后重新进入当前单元格的编辑。
private void Dgv_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    string value = dgv[e.ColumnIndex, e.RowIndex].Value?.ToString();
    // 值为空时,只退出编辑模式,不做任何操作。
    if (string.IsNullOrEmpty(value))  
    {
        Console.WriteLine("value is null or empty."); 
    }
    // 如果能转换,则移动到下一行。
    else if (double.TryParse(value, out double result))
    {
        dgv.CurrentCell = dgv[e.ColumnIndex, e.RowIndex + 1];
    }
    // 如果不能转换为数字,则弹出对话框,然后继续进入编辑模式。
    else
    {
        MessageBox.Show("字符串格式不正确。");
        dgv.BeginEdit(true);
    }
}

附:ProcessCmdKey 函数简介

定义

protected virtual bool ProcessCmdKey(ref Message msg, Keys keyData);

参数列表

msg:通过引用传递的 Message,它表示要处理的窗口消息。
keyData:Keys 值之一,它表示要处理的键。

返回类型

如果字符已由控件处理,则为 true;否则为 false。

使用说明

在消息预处理过程中调用此方法,以处理命令键。命令键是始终比常规输入键具有优先权的键。命令键的示例包括快捷键和菜单快捷方式。此方法必须返回 true,以指示它已经处理完命令键,或者 false,以指示该键不是命令键。仅当控件承载在 Windows 窗体应用程序中或充当 ActiveX 控件时,才调用此方法。

ProcessCmdKey 方法首先确定控件是否有 ContextMenu,如果有,则允许 ContextMenu 处理命令键。如果命令键不是菜单快捷方式,且控件有父级,那么该键传递到父级的 ProcessCmdKey 方法。净效果是命令键在控件层次结构中向上“冒”。除了用户按下的键外,键数据还指示哪些(如果有的话)修改键与该键同时按下。修改键包括 SHIFT、CTRL 和 ALT 键。

对继承者的说明: 在派生类中重写 ProcessCmdKey 方法时,控件应返回 true 以指示它已处理该键。对于未由该控件处理的键,应返回调用基类的 ProcessCmdKey 方法的结果。控件很少需要重写此方法(即使有的话)。

猜你喜欢

转载自blog.csdn.net/weixin_43145361/article/details/100079420
今日推荐