10

这似乎是一个非常简单且非常普遍的问题。我能想到的最简单的例子是:

该表单有五个复选框,上面有一个“全选/全选”复选框。当用户选择检查所有复选框时,我会切换“孩子”的状态 - 显然,在我完成所有复选框的设置之前,我不想触发所有孩子的检查事件。

我找不到表单范围的挂起控制事件。如果我只是想念它,那么很好的简单答案。除非我只是缺少一个简单的解决方案,否则暂停表单控制事件的最佳方法是什么(最佳实践?接受的解决方案?)?

4

6 回答 6

6

我以前遇到过这种情况,通常看到人们这样做:

/*SNIP*/

private bool isMassUpdate;

public void Check1_Check(object sender, EventArgs e)
{
   if(!isMassUpdate)
   {
       do some stuff
   }
}

/*SNIP*/

您还可以分离和重新附加事件处理程序,但是,我被告知这可能是内存泄漏的来源。

有关内存泄漏和事件处理程序的信息:它们与附加和分离没有直接联系,但我们在其中一个应用程序中看到,对继承树的事件处理程序的错误引用可能会导致这种情况。

于 2008-11-13T17:47:29.157 回答
5

我在这些情况下所做的不是使用暂停事件的布尔值,而是使用计数器。当计数 > 0 时,则暂停事件,当计数 = 0 时,则恢复事件。如果我有多个可能要求暂停事件的事情,这有助于解决问题。

另一个有用的事情是,如果我需要在一个块中暂停事件,我创建一个 IDisposable 的小助手类,我可以在“使用”块(在 C# 中)中使用它,这样我就不会忘记减少计数器一旦我超出范围。

于 2008-11-13T23:27:15.523 回答
3

根据您的另一个问题,我猜您正在使用 VB .NET。所以,RemoveHandler 是你最好的选择。通常在 VB 中,人们使用 Handles 子句设置事件处理程序。但你也可以这样做:

AddHandler chk1.CheckedChanged, AddressOf DoSomething

DoSomething 可能看起来像这样:

Private Sub DoSomething(ByVal sender As Object, ByVal e As EventArgs)
    ' whatever
End Sub

AddHandler 连接事件,所以它会触发。要让它不触发,请使用 RemoveHandler:

RemoveHandler chk1.CheckedChanged, AddressOf DoSomething

在更新子复选框的 Checked 属性之前,请在每个复选框上调用 RemoveHandler;然后当你完成后,调用 AddHandler 将事件处理程序放回去。如果您的所有复选框都使用相同的处理程序,您可以将它们放在一个集合中并循环访问该集合以添加或删除处理程序。

于 2008-11-13T17:44:21.690 回答
1

您还可以考虑处理按钮的“单击”事件,而不是检查更改。这可能更接近您的意图。

于 2008-11-13T17:51:43.187 回答
1

在我的Visual Basic 6.0应用程序中,我必须处理用户双击所有内容,所以在我的所有事件处理程序中,我有一行检查全局变量

Private bSuspendEvents as Boolean

Private Sub Button1_Click()

    On Error Goto ErrorHandler

    If bSuspendEvents then Exit Sub

    bSuspendEvents = True

    'Do stuff

    NormalExit:
        bSuspendEvents = False
        Exit Sub

    ErrorHandler:
        'Handle Error
        Resume NormalExit

End Sub
于 2008-11-13T21:02:30.540 回答
1

请参阅堆栈溢出问题如何在 C# Windows 窗体中更改控件状态时忽略触发的简单事件?

对于更一般的情况,如果控件之间有复杂的关系,则可以通过检查其自己的 Focused 属性来检查哪个控件触发了事件……每个对象仅依赖于自身。

于 2014-10-03T03:34:55.057 回答