65.9K
CodeProject 正在变化。 阅读更多。
Home

DataGridView 事件序列

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (33投票s)

2011年8月15日

CPOL

7分钟阅读

viewsIcon

203198

downloadIcon

11627

一个有用的工具,可以帮助您在导航 DataGridView 时理解 DataGridView 事件。

引言

DataGridView 控件在用户浏览网格时会生成许多事件。有单元格进入/退出、行进入/退出、单元格和行验证事件等。要最好地利用这些事件,您需要了解它们何时发生,以及当您以不同方式响应这些事件时会发生什么。本文提供

  • 一个包含网格和事件日志的应用程序。通过编辑网格,您将看到生成的事件日志。
  • 有限状态机图,描述了 EditOnKeystroke 编辑模式的事件序列。

还提供了按钮,允许您影响事件处理程序的行为。例如,当单元格验证失败时,可能会生成不同的事件序列。只需单击一下即可更改这些验证响应。

可执行文件已包含在下载文件中,因此可以轻松尝试并查看 DataGridView 正在触发哪些事件。

我没有支持每个网格事件,如果日志中充斥着所有事件,日志的用处就会减少,但我包含了主要的导航和验证事件。添加新处理程序非常简单,下面将进行说明,如果您需要的话。

让我们先看看应用程序,然后我将更详细地描述事件并介绍状态机。

使用应用程序

DataGridView_Events/Dgv.jpg

该应用程序包含一个事件日志、一个网格和一个工具栏。一运行,网格事件就会触发,并在日志中显示这些事件。单击网格中的任何单元格,日志中将添加更多事件。工具栏按钮可用于模拟验证事件处理程序提供的响应。

工具栏按钮

  • 单元格失败 - 单击时,将启用“单元格失败”状态。每当处理 OnCellValidating 事件时,处理程序将设置 cancel 标志以指示验证失败。再次单击按钮以正常处理事件。
  • 行失败 - 单击时,将启用“行失败”状态。每当处理 OnRowValidating 事件时,处理程序将设置 cancel 标志以指示验证失败。再次单击按钮以正常处理事件。
  • 网格失败 - 单击时,将启用“网格失败”状态。每当处理 OnValidating 事件时,处理程序将设置 cancel 标志以指示验证失败。再次单击按钮以正常处理事件。
  • 拒绝编辑 - 单击时,将启用“拒绝编辑”状态。每当处理 OnCellBeginEdit 事件时,处理程序将设置 cancel 标志以指示拒绝编辑。再次单击按钮以正常处理事件。
  • 记录点击 - 单击时,将启用“记录点击”状态。这会强制在每次单击鼠标时在日志中插入一个空行。这通常使日志更容易理解,因为您可以轻松地看到自上次点击以来触发了哪些事件。
  • 编辑模式 - 网格支持多种编辑模式。每种模式都有不同的事件行为。单击“自动编辑”可循环切换模式,日志将显示当前激活的模式。
  • 清空日志 - 只需单击此按钮即可清空日志。所有日志将丢失。如果您想提前保存日志,可以在事件日志中复制(^C)。

Using the Code

代码并不复杂,我无意将本文作为网格编程教程,因此不会详细介绍。但是,您可能想要添加/删除网格事件。

EventGrid.cs 中,您会看到我支持的事件的处理程序,例如 OnCellEnter()OnCellBeginEdit() 等。

protected override void  OnRowValidating(DataGridViewCellCancelEventArgs e)
{
    base.OnRowValidating(e);
    if (!ctrlInitialised)
    {
        return;
    }
    eventList.AddEvent("OnRowValidating (" + e.ColumnIndex + "," + e.RowIndex + 
                       ") - " + (form1.RowFail ? "FAIL" : "OK"));
    e.Cancel = form1.RowFail;
}

每个处理程序执行以下操作:

  1. 调用基类事件处理程序。
  2. 检查网格是否已初始化。
  3. 使用要显示在日志中的 string 调用 eventList.AddEvent()。我的处理程序会在适当时将单元格索引放入 string 中。
  4. 可选地修改事件参数中的标志,以指示与该事件相关的特定行为。

如果您不关心我支持的事件,只需删除处理程序即可。如果您想支持其他事件,请为新事件添加处理程序并按照上述步骤操作。

理解 DataGridView 事件

我们先从高层次的事件序列入手,然后再详细介绍下载中的状态机。

在一般情况下有几种变化,但让我们先假设网格编辑模式(DataGridView.EditMode)是 EditOnKeystroke,并且所有单元格、所有行和整个网格都是有效的。这允许在不进入编辑模式的情况下浏览网格。当我们从一个单元格移动到另一个单元格时,我们会看到(按顺序)

1. 离开事件

尝试离开单元格时,OnCellLeave() 事件始终会发生。根据移动到的位置,可能会发生其他 Leave 事件。例如:

  • 移动到同一行的单元格 - OnCellLeave()
  • 移动到不同行的单元格 - OnCellLeave(), OnRowLeave()
  • 将焦点移出网格 - OnCellLeave(), OnRowLeave(), OnLeave() (这是网格离开事件)

Leave 事件很简单,因为未来事件不受 Leave 事件处理程序中任何参数更改的影响。

2. 验证事件

Leave 事件完成后,Validation 事件将开始触发。现在,请记住我们在这里假设验证成功,因此 Validating/Validated 事件成对发生,Validating 之后是 Validated。您会从上面的顺序中辨认出来。

  • 移动到同一行的单元格 - OnCellValidating(), OnCellValidated()
  • 移动到不同行的单元格 - OnCellValidating(), OnCellValidated(), OnRowValidating(), OnRowValidated()
  • 将焦点移出网格 - OnCellValidating(), OnCellValidated(), OnRowValidating(), OnRowValidated(), OnValidating(), OnValidated

3. 进入事件

一切都已验证,因此焦点可以按预期移动,事件序列通过触发新单元格的 Enter 事件来完成。

  • 移动到同一行的单元格 - OnCellEnter()
  • 移动到不同行的单元格 - OnRowEnter(), OnCellEnter()
  • 从网格外部移入单元格 - OnRowEnter(), OnCellEnter(), OnEnter() (这是网格进入事件)

将所有这些放在一起,当从有效行 R1 中的有效单元格 C1 移动到行 R2 中的单元格 C2 时,将触发以下事件序列:

  • OnCellLeave(C1)
  • OnRowLeave(R1)
  • OnCellValidating(C1)
  • OnCellValidated(C1)
  • OnRowValidating(R1)
  • OnRowValidated(R1)
  • OnRowEnter(R2)
  • OnCellEnter(C2)

如前所述,这只是一个案例,还有许多变体,因此让我们通过有限状态机(FSM)来跟踪这个案例(即,移动到不同行的单元格)。FSM 处理 EditOnKeystroke 的所有变体,当您熟悉它之后,就很容易理解 EditOnEnter。稍后会介绍更多内容,但现在请查看 DgvFsmMasterEoK.pdf 中的主 FSM。

从图的左上角的状态 1 开始。在此状态下,已选择其中一个单元格但未进行编辑。当选择另一行的单元格时,将过渡到状态 5。这表明事件 OnCellLeave()OnRowLeave()OnCellValidating()(按此顺序)会发生。状态 5 是一个子 FSM,您可以在 DgvFsmA2.pdf 中找到它。现在查看 FSM A2,从状态 1(假设 OnCellValidating() 处理程序指示单元格有效)开始,将过渡到状态 2。此过渡表明事件 OnCellValidated()OnRowValidating() 会发生。接下来,假设 OnRowValidating() 指示行有效,将发生事件 OnRowValidated()OnRowEnter()OnCellEnter(),子 FSM 将退出并返回主 FSM 状态 1。图中事件中显示的(旧)和(新)参数表示提供的参数是指正在离开(旧)还是正在进入(新)的单元格/行。

在完成了这个示例之后,您现在应该能够尝试各种变体(例如,当 OnRowValidating() 事件处理程序指示行无效时会发生什么)。可以尝试使用该应用程序并在 FSM 上跟踪它。

进入编辑

那么,如何将编辑模式更改为 EditOnEnter 呢?主要区别在于主 FSM 的状态 1。状态 1 正在等待用户选择另一个单元格或按键来为该单元格启动编辑模式。对于 EditOnEnter,此状态变为瞬态,即无需等待,因为一旦选择了单元格,它将自动进入编辑模式。不再需要在状态 1 中等待。更改可以在 DgvFsmMasterEoE.pdf 中看到。所有进入状态 1 的输入都会在进入此状态之前的最后一个事件中触发 OnCellBeginEdit() 事件。您的 OnCellBeginEdit() 处理程序可以拒绝编辑,将单元格保留在状态 2 中,或者接受它并像以前一样进入状态 3 的编辑模式。您可能还会注意到状态 3 不再可以通过 Escape 键退出编辑模式,该键将被忽略。没有其他区别,子 FSM 不受影响。

© . All rights reserved.