none
How to remove all handlers of a click event? (I don't know the names of the methods nor the handlers) RRS feed

  • Pergunta

  • How to remove all handlers of a click event?
    Note:  I don´t know the names of the methods nor the handlers.

    Ex;

    //elemento is Button

    EventInfo evInfo = elemento.GetType().GetEvent("Click");
    evInfo.RemoveEventHandler(elemento, XXX);

    Where XXX = Delegate handler
    But, I don´t know who is "Delegate handler"......

    Thanks

     




    quarta-feira, 15 de junho de 2011 20:26

Respostas

  • Ola Felipe... o metodo ClearClick ou ClearEvent... vc pode implementar usar Extension Methods...

     

    o GetInvocationList existem em todos os delegates....

    o problema é que vc so pode manipular o evento "Click" dentro da classe e não fora dela... 
    tipo eu nao posso fazer:

    var button = new Button();

    Delegate handler = button.Click;
    mas dentro da classe Button eu posso fazer
    Delegate handler = this.Click;
    ... lembrando q um evento é um delegate.... uma vez que vc tenha um objeto do tipo Delegate (ou EventHadler que é filho de Delegate) vc tem o GetInvocationList que te retona todos os metodos atribuidos ao evento ... ai vc pode chamar o RemoveEventHandler....
    isso serve mesmo se vc usar expressão lambda...
    button.Click += (sender, args) => { };
    Ate da para acessar o delegate do metodo em uma classe externa... 
    var eventInfo = teste.GetType().GetEvent("Click");
    var methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
    Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, methodInfo);
    mas simplesmente ta dando erro isso ai e não acho o motivo.... ja que no debug os valores do objetos estão corretos....
    então (apenas) teoricamente ... isso deveria funcionar:

    // Seu componente
    Control componente = // Seu Control;
    // Infomarçao do Evento Click
    EventInfo eventInfo = teste.GetType().GetEvent("Click");
    // Invoca o metodo para execução no evento click
    MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
    // Intancia em um delegate o metodo de methodInfo
    Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, methodInfo);
    // Carrega a lista de metodos vinculados no evento
    var invocations = handler.GetInvocationList();
    // Remove todos os metodos do evento
    invocations.ToList().ForEach(item => eventInfo.RemoveEventHandler(this, item));

     

    quinta-feira, 16 de junho de 2011 20:01
    Moderador

Todas as Respostas

  • Ola Felipe,

    Prmeiramente este é um forum brasileiro, então pedimos para usar o portugues aqui, tudo bem ?

    Agora, tente remover os handlers desta maneira:

    var eventInfo = this.GetType().GetEvent("Click");
    var methodInfo = eventInfo.GetRaiseMethod();
    var handler = Delegate.CreateDelegate(typeof(EventHandler), this, methodInfo.Name, false);
    eventInfo.RemoveEventHandler(this, handler);
    


    quarta-feira, 15 de junho de 2011 20:49
    Moderador
  • Olá Rui,

    Pode deixar, usarei o português, desculpe.

    Então, quando tento recuperar o GetRaiseMethod, ele me retorna null.
    var methodInfo = eventInfo.GetRaiseMethod(), a variável "methodInfo" fica null.

    quando eu tento fazer.
    MethodInfo methodInfo = eventInfo.GetAddMethod(), dai ele retorna o "add_click".

    Porém, não serve para criar o delegate.

    Alguma outra idéia ?

    Obrigado.

    quarta-feira, 15 de junho de 2011 21:01
  • Realmente... seu problema é mais complicado do que parece... muita coisa que deveria funcionar não rolou...

    eu cheguei ate o MethodInfo atribuido ao evento:

    var eventInfo = teste.GetType().GetEvent("Click");
    var methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");

    Mas fica dando erro na criação do Delegate mesmo assim...

    var delegateHandler = Delegate.CreateDelegate(eventInfo.EventHandlerType, methodInfo);
    var handlers = delegateHandler.GetInvocationList();
    foreach (var handler in handlers) {
              eventInfo.RemoveEventHandler(teste, handler);
    }

    Vou pensar nisso com mais calma... se eu descobrir algo eu aviso...

    quinta-feira, 16 de junho de 2011 00:02
    Moderador
  • Não é bem o que vc procura... mas o melhor q eu achei foi isso aqui... 

    using System;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace RemoveHandler {
      class Program {
        static void Main(string[] args) {
          var teste = new Teste();
          for (int i = 0; i < 10; i++) {
            teste.Click += teste_Click;
          }
          Console.WriteLine("Antes de Remover");
          teste.OnClick();
    
          teste.ClearClick();
    
          Console.WriteLine("Depois de Remover");
          teste.OnClick();
    
          Console.ReadLine();
        }
    
        static void teste_Click(object sender, KeyPressEventArgs e) {
          Console.WriteLine("Clicou");
        }
    
        static void RemoverHandlers(MulticastDelegate eventDelegate) {
        }
      }
    
      public class Teste {
        public event EventHandler<KeyPressEventArgs> Click;
    
        public void OnClick() {
          if (this.Click != null) this.Click(this, new KeyPressEventArgs('a'));
        }
    
        public void ClearClick() {
          this.ClearEvent(Click, "Click");
        }
    
        public void ClearEvent<TEventArgs>(EventHandler<TEventArgs> handler, string eventName) where TEventArgs : EventArgs {
          var invocations = handler.GetInvocationList();
          var eventInfo = this.GetType().GetEvent(eventName);
          invocations.ToList().ForEach(item => eventInfo.RemoveEventHandler(this, item));
        }
      }
    }
    
    


    quinta-feira, 16 de junho de 2011 00:24
    Moderador
  • Então Rui,

    Isso não resolve também...

    Não tenho o evento "ClearClick()" nem o evento "GetInvocationList()". Isso porque eu não conheço o "handler".

    Eu esqueci de mencionar mas estou trabalhando com WPF e o evento Click está sendo criado no CodeBehind do Xaml.
    Eu fiz um esquema utilizando o XamlWrite e XamlRead para ler as informações do "Button" declarado no controle Xaml, porém so vem as informações de propriedades como backugroud, mas os eventos como o "Click", não são retornados.

    Complicado .........

    :??

    att.

     

    quinta-feira, 16 de junho de 2011 13:35
  • Eu consigo, por exemplo, "desregistrar" o evento "Click" sem saber os handlers ?

    Todas as formas que encontrei ele exige que passe o handler como parâmetros.

    :/

    Abc

    quinta-feira, 16 de junho de 2011 13:37
  • Ola Felipe... o metodo ClearClick ou ClearEvent... vc pode implementar usar Extension Methods...

     

    o GetInvocationList existem em todos os delegates....

    o problema é que vc so pode manipular o evento "Click" dentro da classe e não fora dela... 
    tipo eu nao posso fazer:

    var button = new Button();

    Delegate handler = button.Click;
    mas dentro da classe Button eu posso fazer
    Delegate handler = this.Click;
    ... lembrando q um evento é um delegate.... uma vez que vc tenha um objeto do tipo Delegate (ou EventHadler que é filho de Delegate) vc tem o GetInvocationList que te retona todos os metodos atribuidos ao evento ... ai vc pode chamar o RemoveEventHandler....
    isso serve mesmo se vc usar expressão lambda...
    button.Click += (sender, args) => { };
    Ate da para acessar o delegate do metodo em uma classe externa... 
    var eventInfo = teste.GetType().GetEvent("Click");
    var methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
    Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, methodInfo);
    mas simplesmente ta dando erro isso ai e não acho o motivo.... ja que no debug os valores do objetos estão corretos....
    então (apenas) teoricamente ... isso deveria funcionar:

    // Seu componente
    Control componente = // Seu Control;
    // Infomarçao do Evento Click
    EventInfo eventInfo = teste.GetType().GetEvent("Click");
    // Invoca o metodo para execução no evento click
    MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
    // Intancia em um delegate o metodo de methodInfo
    Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, methodInfo);
    // Carrega a lista de metodos vinculados no evento
    var invocations = handler.GetInvocationList();
    // Remove todos os metodos do evento
    invocations.ToList().ForEach(item => eventInfo.RemoveEventHandler(this, item));

     

    quinta-feira, 16 de junho de 2011 20:01
    Moderador
  • Rui,

    Eu dei uma estudada melhor no seu último exemplo e acho que da pra fazer mais ou menos o que eu preciso.

    Vou fazer alguns testes pra ver se consigo resolver o meu problema. Agora eu entendi o que você fez.

    Obrigado.


    sexta-feira, 17 de junho de 2011 13:41
  • Legal... quando vc tiver a solução compartilha com a gente... pq eu fiquei curioso agora :)
    segunda-feira, 20 de junho de 2011 19:55
    Moderador