2013-01-03 21 views
2

有没有一些方法可以让主窗体监听ClassB的自定义事件的任何提升,而无需参考引发该事件的ClassB的特定实例?类级别而非实例处理自定义事件?

将生成事件的ClassB的实例目前在表单知道的ClassA实例内匿名实例化。

(最后更新:我直接调用MainForm的方法,如我所料是公认的答案to this question没有工作的原因)

更新我怀疑它比我想象的更复杂。下面的引用解释了为什么我对MainForm.DataReady()的调用不起作用 - 以一种令人难以捉摸的方式。

.NET事件的魔法隐藏,当你通过一个实例订阅到B的情况下一个事件,一个被发送过来到B的AppDomain中的事实。如果A不是MarshalByRef,则发送A的值拷贝。现在你已经有了两个单独的A实例,这就是你遇到意外行为的原因。

Cross AppDomain MarshallByRef vs value copy discussion

UPDATE2:

使用:

Debug.WriteLine("SetWaitState executing with Id={0}", AppDomain.CurrentDomain.Id)

而在MainForm本地事件处理程序的上下文中执行MainForm.DataReady(),虽然从ClassB称为表明,他们正在运行在相同的AppDomain每次。这留下了不同的线索作为问题的原因 - 但在每种情况下MainForm.InvokeRequired都返回false。它仍然没有任何意义 - 但至少是定制事件 - 必要时冒出来 - 确实奏效。

下面的代码说明了这些关系。


Class MainForm 
    private A as New ClassA 

    private sub getData 
    A.getData() 'Sets up the com object & callback 
    end sub 

    Private Sub _ClassB_HandleEvent(ResultMessage As String) Handles {some static/shared reference to ClassB}.CustomEvent 
    'do something with the Message 
    End Sub 

End Class 

Class ClassA 

    public sub getData() 
    Dim ComObj as New ComObject 
    Call ComObj.setClient(New ClassB) 
    End Sub 

End Class 

Class ClassB 
    Implements IComObjectClient 
    Public Event CustomEvent(ByVal ResultMessage As String) 

    sub getdata_callback(results() as Object) handles IComObjectClient.getdata_callback 
    ' Get the results 
    RaiseEvent CustomEvent("Got Data") 'because calling MainForm.DataReady() doesn't work 
    end sub 

End Class 
+0

这是不可能的。事件由对象而不是类来提升。您可以为所有对象提供相同的事件处理程序,请使用AddHandler + AddressOf关键字。但是这通常会导致流泪,因为COM事件不会打扰任何类似* sender *参数的传递。 –

回答

1

或忽略的代表一起,只是捕捉A类B类事件,并增加一个新的A级赛事,你的主子可以挂钩太...

喜欢的东西.. 。

Class MainForm 
     private A As ClassA 

     Public Sub _ClassB_HandleEvent(ByVal ResultMessage As String) 
      ' Do Something like.... TextBox1.Text &= ("Received Event Saying - " & ResultMessage) & vbCrLf 
     End Sub 

     Private Sub GetData() 
      A = New ClassA 
      AddHandler A.GotDataFromClassB, AddressOf _ClassB_HandleEvent 
      A.GetData() 
     End Sub 
    End Class 

    Public Class ClassA 
     Public Event GotDataFromClassB(ByVal ResultMessage As String) 
     Private B As ClassB 

     Public Sub GetData() 
      B = New ClassB 
      AddHandler B.CustomEvent, Sub(ResultMessage As String) 
               RaiseEvent GotDataFromClassB(ResultMessage) 
             End Sub 
      Dim ComObj as New ComObject 
      Call ComObj.setClient(B) 
     End Sub 
    End Class 

Class ClassB 
    Implements IComObjectClient 
    Public Event CustomEvent(ByVal ResultMessage As String) 

    sub getdata_callback(results() as Object) handles IComObjectClient.getdata_callback 
    ' Get the results 
    RaiseEvent CustomEvent("Got Data") 
    end sub 
End Class 
+0

这工作。 @ conrad-frix的解决方案可能同样优秀,但这是我决定采用的解决方案。很明显,跨AppDomain事件并没有发挥作用。 –

+0

非常好...很高兴能帮到你! – PGallagher

0

是否有一些方法可以让主窗体监听ClassB的自定义事件的任何引发,而无需引用引发该事件的ClassB的特定实例?

你可以,但你必须

  1. 声明一个公共CustomEventHandler代表
  2. 声明一个变量ClassB的,所以你可以添加处理程序
  3. 传球MainFrom处理程序分为A类

eg

Public Class MainForm 

    Private Sub _ClassB_HandleEvent(ByVal ResultMessage As String) 
     'do something with the Message 
    End Sub 

    Private A As New ClassA 

    Public Sub getData() 

     Dim eh As New ClassB.CustomEventHandler(AddressOf _ClassB_HandleEvent) 'create the delegate 
     A.getData(eh) 'Pass it to ClassA 
    End Sub 
End Class 


Public Class ClassA 

    Public Sub getData(ByVal eh As ClassB.CustomEventHandler) 
     Dim b As New ClassB 
     AddHandler b.CustomEvent, eh 
     Call setClient(b) 
    End Sub 

    Public Sub setClient(ByVal b As ClassB) 
     b.getdata_callback() 
    End Sub 

End Class 

Public Class ClassB 
    Delegate Sub CustomEventHandler(ByVal ResultMessage As String) 'Declare the handler 
    Public Event CustomEvent As CustomEventHandler 

    Sub getdata_callback() 
     RaiseEvent CustomEvent("Got Data") 
    End Sub 

End Class