【问题标题】:Why is my event handler firing two times?为什么我的事件处理程序会触发两次?
【发布时间】:2015-06-08 19:19:58
【问题描述】:

我有一堆要添加到单个父面板的面板,我想将事件侦听器添加到所有面板,但直到它们全部添加到父面板之后(因为我不希望每次添加新面板时都会触发事件侦听器)。所以我使用以下代码:

   Dim temp_object As question_bar = Nothing
   For Each q As Object In review_holder.Controls
       If TypeOf q Is question_bar Then
          temp_object = q
          AddHandler temp_object.Resize, AddressOf temp_object.resize_me
       End If
   Next

   For Each q As Object In review_holder.Controls
      If TypeOf q Is question_bar Then
         temp_object = q
         temp_object.resize_me()
      End If
   Next

但我注意到 resize_me() 子例程会为每个控件触发两次。我只希望它开火一次。所以我用这段代码追踪了它

MsgBox((New System.Diagnostics.StackTrace).GetFrame(1).GetMethod.Name)

我看到每次调用它的调用方法都是这个子例程和_Lambda$_365。那是什么呀?我如何知道它来自哪里?

顺便说一句,这是一个使用 VS2012 的 winforms 应用程序。

编辑 ---------------------------------- --------------------------

Public Sub resize_me()

 MsgBox((New System.Diagnostics.StackTrace).GetFrame(1).GetMethod.Name)

 If Me.minimized = True Then
    Me.Height = 0
    Exit Sub
 End If

 number_panel.Width = my_parent.number_width
 number_text.Width = my_parent.number_width
 number_separator.Left = number_panel.Right
 question_panel.Left = number_separator.Right
 question_panel.Width = question_panel.Parent.Width * initial_question_width + (question_padding * 2)


End Sub

【问题讨论】:

  • 为什么是第二个循环?当您将控件添加到面板时,会自动调用 Resize 事件处理程序,因此您无需在第二个循环中再次调用它
  • 该控件之前已添加到父控件。第一个循环只是将事件处理程序添加到它们,它不调用事件。如果我离开第二个循环,那么所有面板都不会调整大小。
  • 那你resize_me方法里面的代码是什么?
  • 只是一些基本的高度和宽度变化:(编辑添加代码到问题)
  • 我同意@Steve,不需要第二个循环。添加事件处理程序后,只需在第一个循环的 if 语句中移动 temp_object.resize_me() 调用即可。此外,控件很可能正在调用resize_me() 方法,因为当您更改宽度时,它可能会触发控件的Resize 事件,再次调用您的子例程。

标签: vb.net events addhandler


【解决方案1】:

在调整大小事件中更改大小属性可以解释为什么您的代码会再次被调用。通常我会尽量避免这种情况,但这并不总是可能的。在这些情况下,一个作为标志来阻止重新进入的全局变量可以挽救这一天

Dim insideResize As Boolean

Public Sub resize_me()

 if insideResize = True Then
     Exit Sub
 End if

 insideResize = True
 Try
    If Me.minimized = True Then
       Me.Height = 0
       Exit Sub
    End If

    number_panel.Width = my_parent.number_width
    number_text.Width = my_parent.number_width
    number_separator.Left = number_panel.Right
    question_panel.Left = number_separator.Right
    question_panel.Width = question_panel.Parent.Width * initial_question_width + (question_padding * 2)
  Finally
    insideResize = False
  End Try

End Sub

为了安全起见,请记住始终使用 Try/Finally 块,以确保当您从 Resize 事件退出时,全局标志正确设置回 false。

【讨论】:

  • 感谢您的代码。这似乎是个好主意,我已将其添加到我的代码中,但不幸的是没有任何改变。它仍然被调用两次。对 resize 事件的调用是在第二个循环中的原因是因为我需要等到所有控件都已添加,以便它们最终都具有相同的大小。如果我在第一个面板上调用它并且第二个面板大于第一个面板,那么我需要在第一个面板上再次调用它。如果我等到所有内容都放入,那么我只需要为每个调用一次,它们都具有相同的大小。
猜你喜欢
  • 1970-01-01
  • 2014-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多