DataGridView:如何使Enter键添加新行而不是更改当前单元格?

时间:2010-01-08 20:33:30

标签: .net winforms datagridview

如何使Enter键在Winforms DataGridViewTextBoxCell中表现得像在正常的Winforms TextBox中一样(在文本中添加新行,而不是更改当前单元格)?

3 个答案:

答案 0 :(得分:9)

好吧,我发现了如何解决这个问题。首先,创建一个名为CustomDataGridViewTextBoxEditingControl的类,该类派生自DataGridViewTextBoxEditingControl,并覆盖EditingControlWantsInputKey,如下所示:

public class CustomDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl
    {
        public override bool EditingControlWantsInputKey(
        Keys keyData, 
        bool dataGridViewWantsInputKey)
        {
            switch (keyData & Keys.KeyCode)
            {
                case Keys.Enter:
                    // Don't let the DataGridView handle the Enter key.
                    return true;
                default:
                    break;
            }

            return base.EditingControlWantsInputKey(keyData, dataGridViewWantsInputKey);
    }
}

这会阻止DataGridView处理Enter键并更改当前单元格。但是,它不会使Enter键添加新行。 (似乎DataGridViewTextBoxEditingControl已删除了Enter键的功能)。因此,我们需要覆盖OnKeyDown并自己实现这些功能,如下所示:

protected override void OnKeyDown(KeyEventArgs e)
{
    switch (e.KeyCode & Keys.KeyCode)
    {
        case Keys.Enter:
            int oldSelectionStart = this.SelectionStart;
            string currentText = this.Text;

            this.Text = String.Format("{0}{1}{2}",
                currentText.Substring(0, this.SelectionStart),
                Environment.NewLine,
                currentText.Substring(this.SelectionStart + this.SelectionLength));

            this.SelectionStart = oldSelectionStart + Environment.NewLine.Length;
            break;
        default:
            break;
    }

    base.OnKeyDown(e);
}

然后,创建一个名为CustomDataGridViewTextBoxCell的类,该类派生自DataGridViewTextBoxCell,并覆盖EditType属性以返回CustomDataGridViewTextBoxEditingControl的类型。

public class CustomDataGridViewTextBoxCell : DataGridViewTextBoxCell
{
    public override Type EditType
    {
        get
        {
            return typeof(CustomDataGridViewTextBoxEditingControl);
        }
    }
}

执行此操作后,您可以将现有列上的CellTemplate属性设置为CustomDataGridViewTextBoxCell,也可以创建一个派生自DataGridViewColumn且预设为CellTemplate的类到CustomDataGridViewTextBoxCell,你就会全力以赴!

答案 1 :(得分:5)

您可以通过将DataGridViewCellStyle.WrapMode属性设置为true来执行此操作。来自MSDN:

  

如果某个单元格的WrapMode为False   包含文本,单元格显示   文本在一行上,并显示   任何嵌入的换行符都是框   字符。如果WrapMode为True   包含文本的单元格,单元格   将换行符显示为行   打破,但也包装任何行   超过细胞的宽度。

您可以通过访问单元格上的Style属性或通过使用列的DefaultCellStyle访问列中的所有单元格来为特定单元格设置此项。

[更新] 要在DataGridView中有选择地禁用Enter键,请将Message Filter添加到包含DataGridView的Form中,如下所示:

private KeyMessageFilter m_filter = null;

private void Form1_Load(object sender, EventArgs e)
{
    m_filter = new KeyMessageFilter(this); 
    Application.AddMessageFilter(m_filter);

}

这是消息过滤器类:

public class KeyMessageFilter : IMessageFilter
{
    private Form m_target = null;

    public KeyMessageFilter(Form targetForm)
    {
        m_target = targetForm;
    }

    private const int WM_KEYDOWN = 0x0100;

    private const int WM_KEYUP = 0x0101;


    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            //Note this ensures Enter is only filtered if in the 
            // DataGridViewTextBoxEditingControl and Shift is not also  pressed.
            if (m_target.ActiveControl != null && 
                m_target.ActiveControl is DataGridViewTextBoxEditingControl && 
                (Keys)m.WParam == Keys.Enter && 
                (Control.ModifierKeys & Keys.Shift) != Keys.Shift)
            {
                return true;
            }

        }

        return false;
    }
}

现在,编辑文本时会禁用Enter键,您必须按Tab键才能移动到下一个单元格。 Shift + Enter仍然会为您正在编辑的文本添加换行符。

希望这有帮助。

答案 2 :(得分:0)

尽管@Zach Johnson已经回答了这个问题的主要部分,但他的代码对我不起作用。在花费了很长时间并阅读了不同的线程之后,我意识到您还必须设置一些属性才能完成该工作。这是完整的代码,因此您可以运行一个示例: 定义CustomDataGridViewTextBoxCell:

<packaging>pom</packaging>

然后定义类class CustomDataGridViewTextBoxCell: DataGridViewTextBoxCell { public override Type EditType => typeof(CustomDataGridViewTextBoxEditingControl); }

CustomDataGridViewTextBoxEditingControl

然后定义class CustomDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl { public override bool EditingControlWantsInputKey( Keys keyData, bool dataGridViewWantsInputKey) { switch (keyData & Keys.KeyCode) { case Keys.Enter: // Don't let the DataGridView handle the Enter key. return true; default: break; } return base.EditingControlWantsInputKey(keyData, dataGridViewWantsInputKey); } protected override void OnKeyDown(KeyEventArgs e) { switch (e.KeyCode & Keys.KeyCode) { case Keys.Enter: int oldSelectionStart = this.SelectionStart; string currentText = this.Text; this.Text = String.Format("{0}{1}{2}", currentText.Substring(0, this.SelectionStart), Environment.NewLine, currentText.Substring(this.SelectionStart + this.SelectionLength)); this.SelectionStart = oldSelectionStart + Environment.NewLine.Length; break; default: break; } base.OnKeyDown(e); } }

DataGridViewRolloverCell

之后,定义类public class DataGridViewRolloverCell : DataGridViewTextBoxCell { public override Type EditType => typeof(CustomDataGridViewTextBoxEditingControl); }

DataGridViewCustomColumn

现在,如果您有一个名为public class DataGridViewCustomColumn : DataGridViewColumn { public DataGridViewCustomColumn() { this.CellTemplate = new CustomDataGridViewTextBoxCell(); } } 的{​​{1}},则代码将如下所示:

DatagridViewControl

现在重要: 您仍然必须在dgv中将属性DataGridViewCustomColumn col = new DataGridViewCustomColumn(); dgv.Columns.Add(col); 设置为DefaultCellStyle。在设计器中或使用以下代码进行操作:

WrapText

也不要忘记将属性true设置为DataGridViewCellStyle dataGridViewCellStyle1 = DataGridViewCellStyle(); dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText; dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; this.dgv.DefaultCellStyle = dataGridViewCellStyle1; 。 然后它将起作用。