Click here to Skip to main content
15,867,488 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I have a contextmenustrip and want to bind each "Click" event from each ToolStripMenuItem to another target control that has also a "Click" event - i.e. another Button.
Due to the dynamic control creation at runtime (of the target buttons) I have to subscript the source event from the ToolStripMenuItem and to bind it to the target control.

I tried to use already Delegete.CreateDelegate() but got target missmatch exceptions. So a simple working sample in C# or vb.net would be really nice!

Thank you all!

What I have tried:

I tried to use already Delegete.CreateDelegate() but got target missmatch exceptions.
Posted
Updated 11-Apr-18 0:53am
Comments
Mehdi Gholam 10-Apr-18 11:34am    
How are you creating your controls?
You can bind to click when you create the controls.

When I want to do something like that, I create a method that performs the desired action, and call it from both event handlers. No reflection or weird programming is required (or desired).
 
Share this answer
 
v2
Comments
Maciej Los 10-Apr-18 16:16pm    
5ed!
As mentioned in Solution 1, there are many other ways of doing this—most importantly, you can change the overall architecture of this too, make them click something else and then initiate the function on other two operations. That would be much simpler.

In the reflection, you can work around with the EventInfo objects to see when something happened and then delegate it. Microsoft has just the documentation for that part that lets you add a delegate to the event on runtime and then you can do what you wanted to (click on another button). See this, How to: Hook Up a Delegate Using Reflection | Microsoft Docs[^]

The main question is: How would you trigger the click event? Since there is no btn.Click() function, you are better going to use the btn_Click event handler to imitate as if you clicked the button. In that case, you would need to pass the parameters for that, a typical button handler requires,
C#
public void btn_Click(object sender, EventArgs e) { }

So, you can do that using,
C#
btn_Click(secondBtn, null); // Or create an object for that 'e'!

Now, if you think this is ugly. You would then need to use some sort of UI automation script that does that for you. Apart from this, another solution won't be easier to take care of.

c# - Getting event via reflection - Stack Overflow[^]
 
Share this answer
 
Comments
Maciej Los 10-Apr-18 16:17pm    
5ed!
Afzaal Ahmad Zeeshan 10-Apr-18 17:45pm    
Thank you, Maciej.
Hi,

I found this working solution on: c# - Is it possible to "steal" an event handler from one control and give it to another? - Stack Overflow[^]


XML
Private Shared Sub CopyEvents(ByVal source As Object, ByVal target As Object, ParamArray events As String())
    Dim sourceType As Type = source.[GetType]()
    Dim targetType As Type = target.[GetType]()
    Dim invoker As MethodInfo = GetType(MethodAndSource).GetMethod("Invoke")
    For Each eventName As String In events
        Dim sourceEvent As EventInfo = sourceType.GetEvent(eventName)
        If sourceEvent Is Nothing Then
            Console.WriteLine("Can't find {0}.{1}", sourceType.Name, eventName)
            Continue For
        End If

        Dim raiseMethod As MethodInfo = sourceType.GetMethod("On" & sourceEvent.Name, BindingFlags.Instance Or BindingFlags.[Public] Or BindingFlags.NonPublic)
        If raiseMethod Is Nothing Then
            Console.WriteLine("Can't find {0}.On{1}", sourceType.Name, sourceEvent.Name)
            Continue For
        End If

        Dim targetEvent As EventInfo = targetType.GetEvent(sourceEvent.Name)
        If targetEvent Is Nothing Then
            Console.WriteLine("Can't find {0}.{1}", targetType.Name, sourceEvent.Name)
            Continue For
        End If

        Dim methodAndSource As MethodAndSource = New MethodAndSource(raiseMethod, source)
        Dim handler As [Delegate] = [Delegate].CreateDelegate(sourceEvent.EventHandlerType, methodAndSource, invoker)
        targetEvent.AddEventHandler(target, handler)
    Next
End Sub

Private Class MethodAndSource

    Private ReadOnly method As MethodInfo

    Private ReadOnly source As Object

    Friend Sub New(ByVal method As MethodInfo, ByVal source As Object)
        Me.method = method
        Me.source = source
    End Sub

    Public Sub Invoke(ByVal sender As Object, ByVal args As EventArgs)
        method.Invoke(source, New Object() {args})
    End Sub
End Class

' Sample call:
    CopyEvents(sourceToolTripMenu, targetControl, "Click") 


It works great for my purpose!
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900