2013-01-03 24 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