Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C#
  4. Removing Handler... URGENT

Removing Handler... URGENT

Scheduled Pinned Locked Moved C#
csharphelpquestion
6 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Shubhabrata Mohanty
    wrote on last edited by
    #1

    Hi, To remove Event Handlers from my all controls in the form, I want to use a generic code as follows. 1) Run through all controls in the Form 2) Run through all Events of a control using Reflection .GetEvents() 3) For each Event, I want to get the Delegate, so that I can remove all using GetInvocationList(). but .NET doesn't provide any property to get delegate for the Event Handler. Please help. How can I get the Delegate for the Event Handler.

    H 1 Reply Last reply
    0
    • S Shubhabrata Mohanty

      Hi, To remove Event Handlers from my all controls in the form, I want to use a generic code as follows. 1) Run through all controls in the Form 2) Run through all Events of a control using Reflection .GetEvents() 3) For each Event, I want to get the Delegate, so that I can remove all using GetInvocationList(). but .NET doesn't provide any property to get delegate for the Event Handler. Please help. How can I get the Delegate for the Event Handler.

      H Offline
      H Offline
      Heath Stewart
      wrote on last edited by
      #2

      The EventInfo contains information about an event, which describes add and remove accessors. It also has a method to remove an event handler, EventInfo.RemoveEventHandler. In order to call this you must get the delegate for the event handler (the target method). To do this you need to get the field corresponding to the event that is the delegate. By default in C# at least, that field has the same name as the event. So, you can use EventInfo.Name then call Type.GetField with the name and the right BindingFlags. Cast the field value to Delegate and then you can get the invocation list, i.e. each target added to the delegate (a multicast delegate). Below is a quick sample I threw together.

      using System;
      using System.Reflection;
       
      class Test
      {
      public event EventHandler TestEvent;
       
      public static void Main(string[] args)
      {
      Test t = new Test();
       
      Console.WriteLine("Adding event handlers");
      for (int i = 0; i < 5; i++)
      {
      t.TestEvent += new EventHandler(new Test(i).OnTestEvent);
      Console.WriteLine("Added event handler to test " + i);
      }
       
      Console.WriteLine("Calling event");
      if (t.TestEvent != null)
      {
      t.TestEvent(t, EventArgs.Empty);
      }
       
      Console.WriteLine("Removing event handlers");
      RemoveAllHandlers(t);
       
      Console.WriteLine("Calling event again");
      if (t.TestEvent != null)
      {
      t.TestEvent(t, EventArgs.Empty);
      }
      }
       
      Test()
      {
      }
       
      int index = 0;
      Test(int index)
      {
      this.index = index;
      }
       
      void OnTestEvent(object sender, EventArgs e)
      {
      Console.WriteLine("Handled from test " + index);
      }
       
      static void RemoveAllHandlers(Test test)
      {
      Type t = test.GetType();
      foreach (EventInfo ei in t.GetEvents())
      {
      // Assumes compiler-generated events.
      FieldInfo fi = t.GetField(ei.Name, BindingFlags.Public |
      BindingFlags.NonPublic | BindingFlags.Instance);
      if (fi != null)
      {
      Delegate d = (Delegate)fi.GetValue(test);
      foreach (Delegate handler in d.GetInvocationList())
      {
      Test target = handler.Target as Test;
      if (target != null)
      {
      Console.WriteLine("Removing event handler from test " + target.index);
      }
      ei.RemoveEventHandler(test, handler);
      }
      }
      }
      }
      }

      S 1 Reply Last reply
      0
      • H Heath Stewart

        The EventInfo contains information about an event, which describes add and remove accessors. It also has a method to remove an event handler, EventInfo.RemoveEventHandler. In order to call this you must get the delegate for the event handler (the target method). To do this you need to get the field corresponding to the event that is the delegate. By default in C# at least, that field has the same name as the event. So, you can use EventInfo.Name then call Type.GetField with the name and the right BindingFlags. Cast the field value to Delegate and then you can get the invocation list, i.e. each target added to the delegate (a multicast delegate). Below is a quick sample I threw together.

        using System;
        using System.Reflection;
         
        class Test
        {
        public event EventHandler TestEvent;
         
        public static void Main(string[] args)
        {
        Test t = new Test();
         
        Console.WriteLine("Adding event handlers");
        for (int i = 0; i < 5; i++)
        {
        t.TestEvent += new EventHandler(new Test(i).OnTestEvent);
        Console.WriteLine("Added event handler to test " + i);
        }
         
        Console.WriteLine("Calling event");
        if (t.TestEvent != null)
        {
        t.TestEvent(t, EventArgs.Empty);
        }
         
        Console.WriteLine("Removing event handlers");
        RemoveAllHandlers(t);
         
        Console.WriteLine("Calling event again");
        if (t.TestEvent != null)
        {
        t.TestEvent(t, EventArgs.Empty);
        }
        }
         
        Test()
        {
        }
         
        int index = 0;
        Test(int index)
        {
        this.index = index;
        }
         
        void OnTestEvent(object sender, EventArgs e)
        {
        Console.WriteLine("Handled from test " + index);
        }
         
        static void RemoveAllHandlers(Test test)
        {
        Type t = test.GetType();
        foreach (EventInfo ei in t.GetEvents())
        {
        // Assumes compiler-generated events.
        FieldInfo fi = t.GetField(ei.Name, BindingFlags.Public |
        BindingFlags.NonPublic | BindingFlags.Instance);
        if (fi != null)
        {
        Delegate d = (Delegate)fi.GetValue(test);
        foreach (Delegate handler in d.GetInvocationList())
        {
        Test target = handler.Target as Test;
        if (target != null)
        {
        Console.WriteLine("Removing event handler from test " + target.index);
        }
        ei.RemoveEventHandler(test, handler);
        }
        }
        }
        }
        }

        S Offline
        S Offline
        Shubhabrata Mohanty
        wrote on last edited by
        #3

        Thanks Heath for your help. I got it what you explained but when I try that with this sample code, it didn't work. Please help me. Yoour help is appreciated. I have a TextBox "textBox1" in my windows form. I have a handler for TextChanged event. I am trying to remove this using this code. but it doesn't work. Please help. foreach(EventInfo ev in textBox1.GetType().GetEvents()) { FieldInfo fi = textBox1.GetType().GetField(ev.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null) { Delegate d = (Delegate)fi.GetValue(textBox1); foreach(Delegate handler in d.GetInvocationList()) { ev.RemoveEventHandler(this, handler); } } }

        H 1 Reply Last reply
        0
        • S Shubhabrata Mohanty

          Thanks Heath for your help. I got it what you explained but when I try that with this sample code, it didn't work. Please help me. Yoour help is appreciated. I have a TextBox "textBox1" in my windows form. I have a handler for TextChanged event. I am trying to remove this using this code. but it doesn't work. Please help. foreach(EventInfo ev in textBox1.GetType().GetEvents()) { FieldInfo fi = textBox1.GetType().GetField(ev.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (fi != null) { Delegate d = (Delegate)fi.GetValue(textBox1); foreach(Delegate handler in d.GetInvocationList()) { ev.RemoveEventHandler(this, handler); } } }

          H Offline
          H Offline
          Heath Stewart
          wrote on last edited by
          #4

          Most - if not all - of the Windows Forms controls provided by the .NET Framework do not use the event name as the field name. Please use ildasm.exe installed with the .NET Framework SDK to see what the fields are. Take the add_TextChanged method (the add accessor method for the Control.TextChanged event):

          .method public hidebysig specialname instance void
          add_TextChanged(class [mscorlib]System.EventHandler 'value') cil managed
          {
          // Code size 18 (0x12)
          .maxstack 8
          IL_0000: ldarg.0
          IL_0001: call instance class [System]System.ComponentModel.EventHandlerList [System]System.ComponentModel.Component::get_Events()
          IL_0006: ldsfld object System.Windows.Forms.Control::EventText
          IL_000b: ldarg.1
          IL_000c: callvirt instance void [System]System.ComponentModel.EventHandlerList::AddHandler(object,
          class [mscorlib]System.Delegate)
          IL_0011: ret
          } // end of method Control::add_TextChanged

          You can use ildasm.exe (or an application like .NET Reflector that can also decompile source code) to view the System.ComponentModel.EventHandlerList, System type. This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Customer Product-lifecycle Experience Microsoft [My Articles] [My Blog]

          S 1 Reply Last reply
          0
          • H Heath Stewart

            Most - if not all - of the Windows Forms controls provided by the .NET Framework do not use the event name as the field name. Please use ildasm.exe installed with the .NET Framework SDK to see what the fields are. Take the add_TextChanged method (the add accessor method for the Control.TextChanged event):

            .method public hidebysig specialname instance void
            add_TextChanged(class [mscorlib]System.EventHandler 'value') cil managed
            {
            // Code size 18 (0x12)
            .maxstack 8
            IL_0000: ldarg.0
            IL_0001: call instance class [System]System.ComponentModel.EventHandlerList [System]System.ComponentModel.Component::get_Events()
            IL_0006: ldsfld object System.Windows.Forms.Control::EventText
            IL_000b: ldarg.1
            IL_000c: callvirt instance void [System]System.ComponentModel.EventHandlerList::AddHandler(object,
            class [mscorlib]System.Delegate)
            IL_0011: ret
            } // end of method Control::add_TextChanged

            You can use ildasm.exe (or an application like .NET Reflector that can also decompile source code) to view the System.ComponentModel.EventHandlerList, System type. This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Customer Product-lifecycle Experience Microsoft [My Articles] [My Blog]

            S Offline
            S Offline
            Shubhabrata Mohanty
            wrote on last edited by
            #5

            Thanks a lot for your help. But when I checked it in ILDASM, I found that each control uses different standards. For e.g. for SelectedIndexChanged has a filed called EVENT_SELECTEDCHANGED. So the generic code that I am thinking of may not work properly. Pls advise.

            H 1 Reply Last reply
            0
            • S Shubhabrata Mohanty

              Thanks a lot for your help. But when I checked it in ILDASM, I found that each control uses different standards. For e.g. for SelectedIndexChanged has a filed called EVENT_SELECTEDCHANGED. So the generic code that I am thinking of may not work properly. Pls advise.

              H Offline
              H Offline
              Heath Stewart
              wrote on last edited by
              #6

              A better question would be, what are you trying to do anyway? There may be better ways to solve your problem. For example, if you don't want event handlers to fire under a certain condition, use a state variable and don't run all or the brunt of your event handler code if that state variable is set. If you have a lot of code to synchronize you might use Monitor.TryEnter against a singleton used by the entire application. This posting is provided "AS IS" with no warranties, and confers no rights. Software Design Engineer Developer Division Customer Product-lifecycle Experience Microsoft [My Articles] [My Blog]

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups