Add EventHandler at Runtime

  • Thread starter Thread starter lagay
  • Start date Start date
L

lagay

I have a class library that is called from a form that adds controls to the
form at runtime. I am currently working on creating a PictureBox control at
runtime and am having problems trying to hook up code to the click event of
the PictureBox. The form will contain the code for the click event and I
need to add this event to the PictureBox control at runtime from the class
library.

myPictureBox.Click += new EventHandler(event_name);

I know I need to use Reflection; but there are many methods that have been
removed from the compactframework that I just can't figure out how to
accomplish what I need to do. Has anyone done this before?

Thanks,

Lisa
 
Lisa,

The PictureBox was implemented entirely in managed code, and so it -- like
DataGrid and Panel -- support all of the events that are inherited from the
base Control class. As this applies to your question, it means that:
1) You do not need to use Reflection (and I'm not sure why you think you
need to)
2) If the form send a reference to itself to the class library, the class
library should be able to add the event handler for it.
3) If you want the form to be able to pass any type of control to the class
library, just downcast it to a Control.
4) Otherwise, if the form is always going to pass a PictureBox to the class
library (or vice-versa), then you just pass a reference from one module to
the other.

Perhaps the real question is this: what error messages have you seen? That
is, how do you know you are having a problem doing this? What is not working
and/or not working the way you expect it to??

--
My Best,
Paul Yao

Microsoft eMVP
co-author, .NET Compact Framework Programming with C#
co-author, .NET Compact Framework Programming with VB.NET
http://www.paulyao.com
 
The form is passing the Controls object to the class library. The class
library is creating all controls including the PictureBox and adding them
dynamically to the Controls object. The definition of how the controls look
comes from an XML file. I can not just say

myPictureBox.Click += new EventHandler(pb_Click);

because pb_Click does not exists in the class library; the code for this
event exists in the form. The only way the class library knows about
pb_Click is from the XML file and it is defined as a string. The error
message I get is on the compile for the class library because pb_Click does
not exists in the class library.

So I guess the real question is how can the class library add the
eventhandler for the click event to myPictureBox when the code for the click
event (pb_Click) exists on the form?

Thanks,

Lisa
 
The problem here is that the EventHandler constructor is a special method
and cannot be invoked via reflection. To overcome this we create a helper
class:

public class Invoker
{
private MethodInfo m_mi;
object m_target;
public Invoker(object target, string method)
{
m_target = target;
m_mi = target.GetType().GetMethod(method,
BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance);
if ( m_mi == null )
throw new ArgumentOutOfRangeException("Method not found");
}

public void Invoke(object sender, EventArgs e)
{
if ( m_mi != null )
m_mi.Invoke(m_target, new object[] { sender, e });
}
}

Then, given the target control and the event handler ( we have the form
myForm and the event handler method name event_name ) we do the following:

// Get the descriptor of the event (by name).
EventInfo ei = myPictureBox.GetType().GetEvent("Click");
// Create an instance of Invoker that targets the event handler
Invoker invoker = new Invoker(myForm, event_name);
// Add the event handler exposed by Invoker
ei.AddEventHandler(myPictureBox, new EventHandler(invoker.Invoke));
 
Alex,

Thank you very much; this is exactly what I was looking for and I got it
working!

Lisa


Alex Feinman said:
The problem here is that the EventHandler constructor is a special method
and cannot be invoked via reflection. To overcome this we create a helper
class:

public class Invoker
{
private MethodInfo m_mi;
object m_target;
public Invoker(object target, string method)
{
m_target = target;
m_mi = target.GetType().GetMethod(method,
BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance);
if ( m_mi == null )
throw new ArgumentOutOfRangeException("Method not found");
}

public void Invoke(object sender, EventArgs e)
{
if ( m_mi != null )
m_mi.Invoke(m_target, new object[] { sender, e });
}
}

Then, given the target control and the event handler ( we have the form
myForm and the event handler method name event_name ) we do the following:

// Get the descriptor of the event (by name).
EventInfo ei = myPictureBox.GetType().GetEvent("Click");
// Create an instance of Invoker that targets the event handler
Invoker invoker = new Invoker(myForm, event_name);
// Add the event handler exposed by Invoker
ei.AddEventHandler(myPictureBox, new EventHandler(invoker.Invoke));

--
Alex Feinman
---
Visit http://www.opennetcf.org
lagay said:
I have a class library that is called from a form that adds controls to the
form at runtime. I am currently working on creating a PictureBox control
at
runtime and am having problems trying to hook up code to the click event
of
the PictureBox. The form will contain the code for the click event and I
need to add this event to the PictureBox control at runtime from the class
library.

myPictureBox.Click += new EventHandler(event_name);

I know I need to use Reflection; but there are many methods that have been
removed from the compactframework that I just can't figure out how to
accomplish what I need to do. Has anyone done this before?

Thanks,

Lisa
 
Back
Top