Max
Max

Reputation: 3583

Issue when trying to get the delegate associated to a Control's event

I am trying to serialize controls to XML and I want to serialize their events' handler.

I am using this bit of code:

Control childCtrl = ....

if (childCtrl.GetType() == typeof(Button)) {
    EventInfo baseEventInfo = childCtrl.GetType().GetEvent("Click");

    EventHandlerList events =
        typeof(Control).GetProperty("Events",
                                    BindingFlags.Instance |
                                    BindingFlags.Public   |
                                    BindingFlags.Static   |
                                    BindingFlags.NonPublic).GetValue(childCtrl, null)
                                      as EventHandlerList;
    object eventField = typeof(Control).GetField("Event" + baseEventInfo.Name,
                                                 BindingFlags.NonPublic |
                                                 BindingFlags.Static).GetValue(childCtrl);
    Delegate aDel = events[eventField];

    xmlSerialisedForm.WriteElementString("Click", aDel.Method.ToString());
}

if (childCtrl.GetType() == typeof(CheckBox)) {
    EventInfo baseEventInfo = childCtrl.GetType().GetEvent("CheckedChanged");

    EventHandlerList events =
      typeof(Control).GetProperty("Events",
                                  BindingFlags.Instance |
                                  BindingFlags.Public   |
                                  BindingFlags.Static   |
                                  BindingFlags.NonPublic).GetValue(childCtrl, null)
                                    as EventHandlerList;
    //Error here: GetField returns null
    object eventField = typeof(Control).GetField("Event" + baseEventInfo.Name,
                                                 BindingFlags.NonPublic |
                                                 BindingFlags.Static).GetValue(childCtrl);
    Delegate aDel = events[eventField];
    xmlSerialisedForm.WriteElementString("CheckedChanged", aDel.Method.ToString());
}

Now I know that the checkbox has a handler bound for the event CheckedChanged; when using the debugger I can see that method in the EventHandlerList:

Enter image description here

Now the same code actually works when dealing with a Button (when I want to get the delegate associated to the Click event). Why is it not working for the CheckBox? What am I missing here?

EDIT: my current workaround (very ugly) that I deduced from calling GetFields on typeof(CheckBox) and looking in the array:

if (childCtrl.GetType() == typeof(CheckBox)) {
    EventHandlerList events =
      typeof(Control).GetProperty("Events",
                                  BindingFlags.Instance |
                                  BindingFlags.Public   |
                                  BindingFlags.Static   |
                                  BindingFlags.NonPublic).GetValue(childCtrl, null)
                                    as EventHandlerList;

    object eventField =
      typeof(CheckBox).GetFields(BindingFlags.NonPublic |
                                 BindingFlags.Static)[0].GetValue(childCtrl);
    Delegate aDel = events[eventField];
    xmlSerialisedForm.WriteElementString("CheckedChanged", aDel.Method.ToString());
}

Upvotes: 3

Views: 897

Answers (1)

CAD bloke
CAD bloke

Reputation: 8798

Rather infuriatingly, the CheckedChanged event seems to have been written in an entirely different fashion to the rest of the Events on the .NET framework. So was CheckStateChanged. Here they are.

typeof(CheckBox).GetField("EVENT_CHECKEDCHANGED",
      BindingFlags.NonPublic | 
      BindingFlags.Static| 
      BindingFlags.Instance | 
      BindingFlags.FlattenHierarchy);
typeof(CheckBox).GetField("EVENT_CHECKSTATECHANGED", 
      BindingFlags.NonPublic |
      BindingFlags.Static|
      BindingFlags.Instance |
      BindingFlags.FlattenHierarchy);

Just to make it more special, you can't treat everything as a CheckBox or those are the only two events you will get.

Upvotes: 2

Related Questions