【问题标题】:Can I make DataGridView.EndEdit trigger the CellValidating event?我可以让 DataGridView.EndEdit 触发 CellValidating 事件吗?
【发布时间】:2009-01-08 01:16:13
【问题描述】:

我在我的 WinForms 应用程序中使用 DataGridView。我的主要目标是使 Enter 键不会移动到网格中的下一行。我仍然希望输入键来验证和结束编辑模式。

我找到了this FAQ entry 并将DataGridView 子类化以覆盖ProcessDialogKey()。如果按下的键是 Enter,我调用 EndEdit(),否则我调用 base.ProcessDialogKey()。

效果很好,只是没有触发 CellValidating 事件。

目前,我只是在调用 EndEdit 之前手动调用我的验证逻辑,但似乎我遗漏了一些东西。

我想我可以调用 OnCellValidating,但我会担心我会错过一些其他事件。我真正想要的是 EndEdit() 的某种风格,其行为就像在添加禁用的网格的最后一行上按 Enter 键一样。

【问题讨论】:

    标签: c# winforms datagridview


    【解决方案1】:

    在您更改 CurrentCell 之前不会调用 CellValidating。所以我解决这个问题的方法是更改​​ CurrentCell,然后切换回当前的。

        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Enter)
            {
                DataGridViewCell currentCell = CurrentCell;
                EndEdit();
                CurrentCell = null;
                CurrentCell = currentCell;
                return true;
            }
            return base.ProcessDialogKey(keyData);
        }
    

    【讨论】:

    • 是的,我见过类似的策略,但绝对感觉像是一个杂牌。不过,我喜欢将 CurrentCell 设置为 null 的想法。我认为其他示例移到下一行然后返回。
    • 它说,operation did not succeed, because the program cannot commit or quit a cell value change 验证失败不是真正的解决方案
    • 请参阅jaminator's answer 了解处理验证错误的方法,但如果验证失败,我可能希望设置行的ErrorText 或其他内容。
    【解决方案2】:

    如果单元格处于编辑模式,JJO 的代码将崩溃。下面避免验证异常:

    DataGridViewCell currentCell = AttachedGrid.CurrentCell;
            try
            {             
                AttachedGrid.EndEdit();
                AttachedGrid.CurrentCell = null;
                AttachedGrid.CurrentCell = currentCell;
            }
            catch 
            {
                AttachedGrid.CurrentCell = currentCell;
                AttachedGrid.CurrentCell.Selected = true; 
            }
    

    来源:Kennet Harris's answer here

    【讨论】:

      【解决方案3】:

      如果您的 DataGridView 的 DataSource 是 BindingSouce,请执行此操作(将其放入您的 Key processing events):

      bds.EndEdit();
      

      如果你的 DataGridView 的 DataSource 是 DataTable:

      this.BindingContext[dgv.DataSource].EndCurrentEdit();
      

      【讨论】:

        【解决方案4】:

        感谢您的解决方案。 我的版本与您的版本略有不同,因为当我移动到另一个单元格时,并且我的代码在单元格验证事件中返回 e.cancel=false 时,会生成一个错误,说:“操作没有成功,因为程序无法提交或退出单元格值更改”。所以我用 try catch 来解决这个问题。

        这是我的代码:

        Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
        
            Dim key As Keys = (keyData And Keys.KeyCode)
        
            If key = Keys.Enter Then
                If MyBase.CurrentCell.ColumnIndex = 1 Then
                    Dim iRow As Integer = MyBase.CurrentCell.RowIndex
        
                    MyBase.EndEdit()
                    Try
                        MyBase.CurrentCell = Nothing
                        MyBase.CurrentCell = MyBase.Rows(iRow).Cells(1)
                        frmFilter.cmdOk_Click(Me, New EventArgs)
                    Catch ex As Exception
                    End Try
        
                    Return True
                End If
            End If
        
            Return MyBase.ProcessDialogKey(keyData)
        End Function
        

        【讨论】:

          【解决方案5】:

          否,但您可以手动触发 CellValidating 事件。只需创建适当的参数。所有事件都是使用观察者模式的类,它们与任何其他方法没有什么不同。如果这不起作用,您可以在单元格上创建一个 KeyPress 事件并模拟在单元格上按 Enter,但这可能会与用户 UI 混淆,只需将克拉放回原处即可。

          【讨论】:

          • 很遗憾,CellValidating 事件的 EventArgs 类没有公共构造函数。
          • 当然,无论如何你都可以使用反射来访问构造函数,但是在单元测试之外,这似乎很糟糕。
          猜你喜欢
          • 1970-01-01
          • 2012-01-24
          • 1970-01-01
          • 2011-03-20
          • 1970-01-01
          • 2019-07-22
          • 2022-06-18
          • 2016-03-20
          • 1970-01-01
          相关资源
          最近更新 更多