Sunday, May 1, 2011

Raising external object's events in C#

If actions is a Panel, am I able to raise the Click event of it's parent? I have this code at the moment, but the Click event isn't a method, so this code is invalid.
Does anyone know how I can achieve this?

actions.Click += delegate(object Sender, EventArgs e)
{
    ((Panel)Sender).Parent.Click();
}
From stackoverflow
  • It's not possible to raise a C# event directly from another class (even if it's public). You could provide a method (with a sufficient access modifier) that raises the event on your behalf and call that method in the other class.

    By the way, this is possible with reflection, but I consider that a dirty hack.

    Charlie Somerville : Could I create a new Panel class the inherits the old one, and then add a method to raise the Click event?
    Mehrdad Afshari : Yes. You should do that.
  • Depending on what framework you are using its possible you don't have to manually invoke the click event on the parent, WPF and ASP.NET for example bubble events up the element tree.

    If that's not an option you can do like Mehrdad suggests.

  • Most types in the CLR that raises events has a protected On[EventName] method that takes care of raising the event. You can invoke this protected method "from the outside" using Reflection:

     Control parent = ((Control)sender).Parent;
     Type parentType = parent.GetType();
     MethodInfo onClickMethod = parentType.GetMethod("OnClick", BindingFlags.Instance | BindingFlags.NonPublic);
    
     onClickMethod.Invoke(parent, new object[] { e });
    
  • The only reason I can think of for why you would want to raise the Click event is if you are simulating user input. Are you working on an automated test driver or something like that? If so, there may be better solutions than sullying the code with test-only auxiliary methods. This comes up first in google, I have no idea if it's any good.

    If you're trying to do this as a kind of flow control in your application itself, I'd take a step back to see if this is the right thing to do at all - it kind of "smells bad".

    Charlie Somerville : I'm trying to get the Click event to bubble up, I'm not using WPF, so it doesn't occur automatically.
  • I implemented this using reflection and extension methods so that I can just invoke (in this case) a LinkLabel click event by just calling:

    var link = new LinkLabel()'
    link.Text = "Some link";
    link.click();
    

    the click() method is an C# extension method:

        public static void click(this LinkLabel linkLabel)
    {
        var e = new LinkLabelLinkClickedEventArgs((LinkLabel.Link)(linkLabel.prop("FocusLink")));
        linkLabel.invoke("OnLinkClicked", e);
    }
    

    which uses another extension methods to:

    • get a private property from the LinkLabel (needed to create the LinkLabelLinkClickedEventArgs object)
    • invoke the OnLinkClicked method (which will fire the event

0 comments:

Post a Comment