【问题标题】:Handling keyboard events for custom DataGridView column type处理自定义 DataGridView 列类型的键盘事件
【发布时间】:2021-12-22 21:25:34
【问题描述】:

在下面的代码中,我扩展了 DataGridViewTextBoxCell 类来控制用户将在此字段中输入的值,为此我需要捕获事件 KeyDown。但是只有当我使用键盘在 DGV 中导航时才会调用该事件。当我编辑单元格的值时,事件不会发生。我的代码中缺少什么?

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DataGridView dataGridView = new DataGridView();

            MyDataGridViewColumn col = new MyDataGridViewColumn();
            dataGridView.Columns.Add(col);
            dataGridView.Rows.Add(new string[] { "0" });
            dataGridView.Rows.Add(new string[] { "1" });
            dataGridView.Rows.Add(new string[] { "2" });
            dataGridView.Rows.Add(new string[] { "3" });

            this.panel1.Controls.Add(dataGridView);
        }
    }

    public class MyDataGridViewColumn : DataGridViewColumn
    {
        public MyDataGridViewColumn()
        {
            this.CellTemplate = new MyDataGridViewTextBoxCell();
        }
    }

    public class MyDataGridViewTextBoxCell : DataGridViewTextBoxCell
    {
        protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
        {
            base.OnKeyDown(e, rowIndex);

            var key = e.KeyCode;
        }
    }

【问题讨论】:

  • 尝试覆盖InitializeEditingControl来订阅单元格的TextBox事件。
  • @Dmitry,感谢您的指示,但我不知道该怎么做。你有一些我可以看到如何做到这一点的例子吗?
  • 目前还不清楚您到底要检查什么。您是否只想允许将某些键输入到文本框中,例如仅数字单元格或仅小数单元格?如果是这种情况,那么正如其他人所指出的那样,您想要订阅网格 EditingControlShowing 事件。当单元格进入“编辑”模式时触发该事件。然后在这种情况下,您会将单元格转换为TextBox,然后订阅TextBoxes.KeyPress 事件。但是,这将起作用;用户仍然可以将无效值“粘贴”到单元格中。因此需要做更多的工作。
  • 以下链接……How to enter letters in one column cell of the table and only numbers in the other column cell?……演示了如何执行此操作并检查可能“粘贴”到单元格中的无效文本。

标签: c# winforms datagridview user-controls datagridviewtextboxcell


【解决方案1】:

这些击键将由编辑控件处理。如果您想为此目的创建自己的自定义列类型,那么您可以这样做:

  1. 通过从DataGridViewTextBoxEditingControl 派生来创建您的编辑控件。然后覆盖 OnKeyDown 并在那里添加您的逻辑。
  2. 通过从MyDataGridViewTextBoxCell 派生来创建您的单元格。然后覆盖EditType 并返回您在上一步中创建的编辑控件的类型。
  3. 最后,通过从DataGridViewTextBoxColumn 派生来创建列,并在构造函数中,将您在上一步中创建的单元格的实例设置为CellTemplate

示例

public class MyDataGridViewTextBoxColumn : DataGridViewTextBoxColumn
{
    public MyDataGridViewTextBoxColumn()
    {
        CellTemplate = new MyDataGridCViewTextBoxCell();
    }
}
public class MyDataGridCViewTextBoxCell : DataGridViewTextBoxCell
{
    public override Type EditType => typeof(MyDataGridViewTextBoxEditingControl);
}
public class MyDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        //Put the logic here
    }
}

注意1:对于不需要创建新列类型的情况,您可以轻松处理DataGridViewEditingControlShowing事件,并检查该事件是否属于您想要的列,然后获取编辑控件(并将其转换为正确的类型),然后处理编辑控件的正确事件,例如您可以查看this example中的第一个代码块。

注意2:如果您有兴趣将自定义属性添加到列/单元格并在编辑控件中使用它们,您可以在这篇文章中找到包含示例代码的分步答案:

【讨论】:

  • 非常感谢,这个例子效果很好,但是现在我有另一个问题,也许你可以帮助我。在控件 MyDataGridViewTextBoxEditingControl 中,我需要创建一些在开始编辑单元格之前需要设置的属性。如何访问这些属性?
  • @DrausioDonini 您通常应该在列、单元格和编辑控件中具有相同的属性。该单元还应实现克隆方法。然后在InitializeEditingControl中,可以设置编辑控件的属性值并使用。
  • 我希望保持原样;它干净,专注且不会太长。尝试将我的评论应用于您的代码,如果您遇到无法解决的问题,一旦您提出新问题,我很乐意提供帮助:)
  • 我之所以更愿意保留这个答案,是因为这篇文章的重点是处理键盘事件,而添加自定义属性只适合您的用例。未来的读者只想处理关键事件,他们不需要添加任何自定义属性,他们可能会对这些属性感到困惑。无论如何,我回答了你的新问题,并将在这里分享另一个帖子的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-02
  • 2014-03-19
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多