Reputation: 4237
Is there some way for the main form to listen for any raise of a custom event of ClassB without reference to the specific instance of ClassB that raised the event?
The instance of ClassB that would generate the event is currently anonymously instantiated inside the ClassA instance the form knows.
(Final update: The reason my direct calls to MainForm methods didn't work as I expected is in the accepted answer to this question. )
Update I suspect that it's more complicated than I thought. The following quote explains why my call to MainForm.DataReady() didn't work - in a maddeningly obscure fashion.
The magic of .NET events hides the fact that, when you subscribe to an event in an instance of B by an instance of A, A gets sent over into B's appdomain. If A isn't MarshalByRef, then a value-copy of A is sent. Now you've got two separate instances of A, which is why you experienced the unexpected behaviors.
Cross AppDomain MarshallByRef vs value copy discussion
Update2:
Using:
Debug.WriteLine("SetWaitState executing with Id={0}", AppDomain.CurrentDomain.Id)
while executing MainForm.DataReady()
in context of a MainForm
local event handler and while called from ClassB
showed they were running in the same AppDomain
each time. That leaves different threads as the reason for the problem -- and yet MainForm.InvokeRequired
returned false in each case. It still doesn't make sense -- but at least the custom events -- bubbled up, as necessary -- did work.
Code below illustrates the relationships.
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
Upvotes: 2
Views: 299
Reputation: 3113
Or ignore Delegates all together, and just capture the Class B Event in Class A, and Raise a New Class A Event which your Main Sub can hook up too...
Something Like...
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
Upvotes: 1
Reputation: 52675
Is there some way for the main form to listen for any raise of a custom event of ClassB without reference to the specific instance of ClassB that raised the event?
You can but you'd have to
e.g.
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
Upvotes: 0