如何处理来自另一个类/实例的成员事件

时间:2010-07-14 15:31:41

标签: c# .net vb.net events event-handling

我试图在应用程序的几个不同部分之间共享一个子菜单,以便它是一致的(不想复制/粘贴。)我认为这很简单。我正在做这样的事情:

 public class MyClientClass
     Private WithEvents ctx As ContextMenuManager = New ContextMenuManager
     Private Sub handler() Handles ctx._myToolstripMenuItem.Click
         ' do something useful
    End Sub
End Class

Public Class ContextMenuManager
    Public WithEvents _myToolstripMenuItem As ToolStripMenuItem

    Public Sub New()
        Me._myToolstripMenuItem = New ToolStripMenuItem
        Me._myToolstripMenuItem.Name = "DoSomehting"
        Me._myToolstripMenuItem.Size = New System.Drawing.Size(48, 20)
        Me._myToolstripMenuItem.Text = "Go!"
    End Sub
End Class

但是那段代码给了我一个错误:类中的'Handles'必须指定一个'WithEvents'变量,'MyBase','MyClass'或'Me'用一个标识符限定。

我为容器应用程序和菜单项提供了WithEvents关键字。是什么赋予了?我错过了什么? C#示例会给出相同的错误吗?

改变焦点以解决另一种方式。处理共享类中的所有事件并使用公共obj触发公共事件:

Private Sub MenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
 Handles ToolStripMenuItem.Click
     ' edit _legacyAttributes instance per specifics
     ' ...
     ' then always raise the same event with the updated payload object
     RaiseEvent TypeChanged(_legacyAttributes)
 End Sub

所以,你可以想象在类中有几十个像这样的处理程序,每一个都修改它的_legacyAttributes,因为它有意义......

3 个答案:

答案 0 :(得分:2)

“withevents”声明是一个非常好的语法糖,就像这样:

WithEvents Foo as Control 
  -- becomes
Dim _Foo as Control
Property Foo as Control
  Get
    Return _Foo
  End Get
  Set(Value as Control)
    If _Foo IsNot Nothing Then
      RemoveHandler _foo.Click,foo_Click
      RemoveHandler _foo.Load,foo_Load
      etc.
    End If
    _Foo = Value
    If _Foo IsNot Nothing Then
      AddHandler _foo.Click,foo_Click
      AddHandler _foo.Load,foo_Load
      etc.
    End If
  End Set
End Property

对于与Foo相关联的每个Handles声明,将有一个RemoveHandler和一个AddHandler。请注意,此类属性声明只能在当前类中完成。一个类没有通用的方法告诉另一个类,设置其中一个属性应该导致事件在前一个类中被订阅。

答案 1 :(得分:1)

不允许额外的间接。您必须像这样编写ContextMenuManager类:

Public Class ContextMenuManager
    Public Event Click As EventHandler
    Private WithEvents _myToolstripMenuItem As ToolStripMenuItem

    Public Sub New()
        ''...
    End Sub

    Private Sub _myToolstripMenuItem_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles _myToolstripMenuItem.Click
        RaiseEvent Click(Me, e)
    End Sub
End Class

现在您可以使用“Handles _ctx.Click”。隐藏ContextMenuManager的实现细节当然是有价值的,因此额外的代码可能是值得的。是的,AddHandler没有这个限制。

答案 2 :(得分:0)

无法找到Handles语法无效的原因,但我确实找到了使用AddHandler附加事件的OK解决方法。所以而不是:

Handles ctx._myToolstripMenuItem.Click

在加载事件或某些初始方法中,我会这样做:

AddHandler ctx._myToolstripMenuItem.Click, AddressOf handlerMethod