Reputation: 1338
Every sample I've seen that refers to this is about mouse clicks and then the example is the same.
I need to specifically raise an event on another control.
I have a panel with an event that I created like this:
Private FlowPanel as new my_FlowLayoutPanel
Addhandler FlowPanel.change, addressof doChange
Public Class my_FlowLayoutPanel
Inherits FlowLayoutPanel
Public Event change(ByVal sender As Object)
Public Const Ver_SCROLL As Integer = &H115
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = Ver_SCROLL Then
RaiseEvent change(Me)
End If
MyBase.WndProc(m)
End Sub
End Class
So when the vertical scroll bar moves, the "change" event fires.
So now, I have another control, (a simple panel) set up like this:
Public Class view_Panel
Inherits System.Windows.Forms.Panel
Protected Overrides Sub WndProc(ByRef m As Message)
Const NCMOUSEMOVE As Integer = &H200
If m.Msg = NCMOUSEMOVE Then
' *** FIRE THE "CHANGE" EVENT ON THE FLOWLAYOUT PANEL
End If
MyBase.WndProc(m)
End Sub
End Class
So, how do I fire the "Change" event from the view_Panel?
Upvotes: 1
Views: 2890
Reputation: 570
Even after reading other answers such as 'Pouya Samie' above (reflect to OnChange
if available), or this more enhanced article "Raising Events Using Reflection" which seems much cleaner but doesn't always work (reflect to MulticastDelegate
)...
So finally got to put all my ideas in order for a generic method to perform this task with a simple syntax:
TriggerEvent(ComboBox1, "OnSelectedIndexChanged")
Notice that the above method is private non-accesible inside the ComboBox1, it is even NOT listed on the IntelliSense list members, but with this reflection method it will work OK:
''' <summary>
''' Manually trigger an existing event in a control.
''' </summary>
''' <param name="ctrlObject">The GUI control that that should be operated (such as ComboBox).</param>
''' <param name="onEventName">The OnEvent function regardless of the scope (such as OnSelectedIndexChanged).</param>
''' <returns><code>True</code> when the method is found invoked and returned successfully; <code>false</code> otherwise.</returns>
Public Function TriggerEvent(ctrlObject As Control, onEventName As String) As Boolean
' Get the reference to the method
Dim methodRef As MethodInfo = ctrlObject.GetType().GetMethod(onEventName, _
System.Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.Static Or _
System.Reflection.BindingFlags.Instance)
If IsNothing(methodRef) Then Return False
' Invoke the method
Try
methodRef.Invoke(ctrlObject, New Object() {EventArgs.Empty})
Return True
Catch ex As Exception
Return False
End Try
End Function
Upvotes: 2
Reputation: 38875
You probably want something like this:
Case WM_HSCROLL
RaiseEvent Scroll(Me, New ScrollEventArgs(ScrollEventType.EndScroll, _
Win32.GetScrollPos(Me.Handle, Win32.SBOrientation.SB_HORZ), _
ScrollOrientation.HorizontalScroll))
Case WM_VSCROLL
RaiseEvent Scroll(Me, New ScrollEventArgs(ScrollEventType.EndScroll, _
Win32.GetScrollPos(Me.Handle, Win32.SBOrientation.SB_VERT), _
ScrollOrientation.VerticalScroll))
ScrollEventArgs
is a standard Net event, so we dont need to define it. Then declare the event as ('change' seems a very poor choice):
Public Event Scroll(ByVal sender As Object, ByVal sa As ScrollEventArgs)
If your Panel needs to do something with the event, use the OnScroll method, which allows the panel to do stuff before the end subscriber gets the event:
Protected Overrides Sub OnScroll(ByVal sa As ScrollEventArgs)
... do stuff
' in cases where you no longer need the event to be passed
' on, dont call this:
MyBase.OnScroll(e)
End Sub
How to use:
Since you subclass both, let the Panel raise the event, the FlowPanel can monitor those events (subscribe to the panel's scroll event) and in that, do whatever you were going to do in Change
. Since the ACTION takes place in/on the panel, better to just handle it there.
Upvotes: 0
Reputation: 3723
EDIT To Call your Event From Another Class you can use reflection
MethodInfo onchange = YourClassInstance.GetType().GetMethod("OnChange", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
onChange.Invoke(YourClassInstance, new object[] { new EventArgs() });
Upvotes: 1