Search code examples
c#for-loopreflectionevent-handlingpanel

Invoking reflected methods for several event listeners C#


I have a windows-form with several panels in it within a Panel[,]. Each time the user clicks any of the panels, I'd like a specific and unique event to handle for the panel clicked. I thought about having a single event that has a switch statement, but I figured it's relatively the same practice and would be messier to work with. Maybe I'm going about the design of the event handlers all wrong..

What I'm trying to do looks similar to this:

Type t = typeof(Program);
var methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name.EndsWith("_click")).ToArray();
char[] cArr = { 'a', 'b', 'c', 'd' };

for(int i = 0; i < 4; i++)
{
    for(int j = 0; j < 4; j++)
    {
        MethodInfo method = methods.Single(
             m => m.Name == cArr[i].ToString() + (j + 1) + "_click");
        //  method.Invoke(null, null);
        //  myPanels[i, j].Click += new EventHandler( );
    }
}

private void a1_click(object sender, System.EventArgs e)
{
    MessageBox.Show("Unique event A1");
}
private void a2_click(object sender, System.EventArgs e)
{
    MessageBox.Show("Unique event A2");
}
//...
private void d4_click(object sender, System.EventArgs e)
{
    MessageBox.Show("Unique event D4");
}

If you know of a better way to do the events from a design approach let me know, as I'd love to understand that. But as for this example goes, how am I supposed to put the method within the EventHandler. If I assigned them manually I could just do something like this:

myPanels[0, 0].Click += new EventHandler(a1_click);

But I'd rather loop through the assignment part, or reconsider the events themselves.

Any help is appreciated.


Solution

  • Perhaps a better approach would be to utilize the parameters instead of different event handlers.

    The following example utilizes the Tag property to differentiate which panel sent the event although you should really utilize the EventArgs by creating an event argument and sending that instead of null.

    void Main()
    {
        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < 4; j++)
            {
                myPanels[i, j].Tag = i +" - " + j;
                myPanels[i, j].Click += button_click;
                // fire the event, note that the panel instance is the sender
                myPanels[i, j].OnClick(null);
            }
        }
    }
    
    private void button_click(object sender, System.EventArgs e)
    {
        var pnl = sender as Panel;
        if (pnl != null && pnl.Tag != null)
            MessageBox.Show("Unique event "+ pnl.Tag.ToString());
    }
    

    If you wanted each panel to implement a special behavior, you can create a subclass of Panel and implement an interface;

    public interface ISpecialMethod{
        void SpecialMethod();
    }
    
    public class SpecialPanel :Panel, ISpecialMethod {
        public void SpecialMethod() {
            /* custom logic*/
        }
    }
    
    private void button_click(object sender, System.EventArgs e)
    {
        var pnl = sender as ISpecialMethod ;
        if (pnl != null)
            pnl.SpecialMethod();
    }
    

    From here the possibilities are endless.