Eventos em C# de maneira simples
Leonel Fraga de Oliveira 02/01/2009 16:14

Olá pessoal!

Como já tinha dito em outro post, vamos ao nosso artigo que tratará de explicar de maneira bem simplificada sobre Eventos em classes.

Por que eu disse "em classes" ao invés de "em componentes"?

Quando eu me refiro a componentes, estou me referindo a elementos visuais, ou seja, que colocamos na interface de usuário, tais como botões, caixas de texto, etc.

Quando eu me refiro a somente classe, estou me referindo a uma classe genérica mesmo, que não é um elemento visual.

Então vamos trabalhar com eventos em classes não visuais? Isso mesmo :-)

Para acompanhar melhor, sugiro que façam o download do exemplo, cujo link está no final do post.

Um evento é uma ação que algum objeto "manda executar" quando acontece alguma coisa com ele. Vamos citar o exemplo de um evento OnClick codificado em um botão:

- Através da caixa de propriedades do botão, codificamos seu evento OnClick, que será executado quando o usuário clicar sobre o botão. O que aparece na propriedade OnClick é o nome do método que será executado.
- O usuário clica sobre o botão.
- Se a propriedade OnClick estiver codificada, o programa executará o que codificamos previamente.

Hum... notou alguma coisa aí?

Citei que "o que aparece na propriedade OnClick é o nome do método que será executado". Sim, um evento é um tipo de propriedade de uma classe!

E o que é armazenado nesta propriedade?

Esta propriedade, que é representada pela figura de um raio quando pesquisamos no code-insight, armazena a referência do método que será executado fora da classe quando alguma ação em especial é executada. Um evento, bem dizer, é um [terror dos programadores]ponteiro[/terror dos programadores] para um método externo à classe.

E como ele representa um método, ele deve ter uma assinatura. Esta assinatura de método é previamente definida como um novo tipo de dados, a qual é dado o nome de delegate. Sim, um delegate representa a assinatura de um método, podendo ser ele anônimo (utilizado em rotinas de ordenação, por exemplo), ou a assinatura de um método de evento.

Um delegate é criado da seguinte forma:

public delegate void MeuDelegate( parametro1,  parametro2...);

onde MeuDelegate é o novo tipo de dados que representa uma assinatura de método.

Para declarar um evento, normalmente usamos a seguinte declaração:

public delegate void MinhaAssinaturaDeEventoEventHandler(object sender, EventArgs e);

Por convenção, ao final do nome do tipo colocamos as palavras "Event Handler", indicando que a assinatura de método em questão é um manipulador de evento; e dois parâmetros: um do tipo object, que representará a instância da classe que está disparando o evento, e um do tipo EventArgs (ou de uma classe derivada), que é uma classe básica do .NET Framework para passar informações do evento que está sendo executado, podendo alterar seu comportamento.

Só para fazer uma comparação, na linguagem Delphi declaramos um delegate da seguinte forma:

type TMeuDelegate = procedure (Sender: Object; e: EventArgs) of object;

Para declarar uma propriedade de evento dentro da nossa classe, utilizamos o modificador event. Veja:

public event <delegate do evento>;

Um evento deve ser público, o tipo de dado dele é event, em seguida vem a assinatura do método deste evento, e por fim o seu nome. Um exemplo prático:

public event EventHandler Click;

Um método onClick típico, sendo que EventHandler é o nome do delegate associado.

E como mandamos a classe executar esta rotina dentro do programa?

Um evento é um método. Quando dentro de nossa classe ocorrer a ação que este método irá disparar, simplesmente executamos a variável como um método, passando seus parâmetros: no parâmetro "sender", passamos a instância da classe que está disparando, neste caso, a variável "this". Em EventArgs, passamos uma instância da classe EventArgs, ou uma classe derivada, caso você queira e essa classe derivada esteja na assinatura do delegate. Veja abaixo:

private void AlgumaCoisa()
{
    ...
    if(MeuManipuladorDeEvento != null)
    {
        MeuManipuladorDeEvento(this,new EventArgs());
    }
    ...
}

Antes de mais nada, vamos lembrar que um evento é um ponteiro para um método. Sendo um ponteiro, ele deve estar apontando para algum lugar.

Por isso, antes de executar o método através deste ponteiro, devemos checar se ele é nulo. Se não for nulo, aí sim executaremos o método em questão.

E como faço este ponteiro apontar para algum lugar dentro do meu programa?

Veja na prática o que devemos fazer:

public Classe1 MeuObjeto = new Classe1();

//Dentro do construtor de um form, por exemplo
public Form1()
{
   InitializeComponent();

   //Atribuindo manualmente os manipuladores de evento
   MeuObjeto.MeuEvento += new MinhaAssinaturaDeEventoEventHandler(MeuMetodo);
}

public MeuMetodo(object sender, EventArgs e)
{
  //Faça o que tem que fazer...
}

Para fazer a atribuição do médodo ao ponteiro, devemos utilizar o operador "+=" e atribuir uma instância do delegate que representa a assinatura do método em questão, passando em seu construtor o nome do método que será executado.

Vamos construir uma classe e dar uma analisada:

using System;
using System.Collections.Generic;
using System.Text;
 
namespace MinhaClasseTeste
{
	#region Classe de argumentos de evento
	public class PensamentosEventArgs : EventArgs
	{
	   public string Pensamento = "";
	   public bool SeguirEmFrente = true;

	   public PensamentosEventArgs()
	   { }

	   public PensamentosEventArgs(string pPensamento, bool pSeguirEmFrente)
	   {
		   this.Pensamento = pPensamento;
		   this.SeguirEmFrente = pSeguirEmFrente;
	   }
   }
   #endregion

   public delegate void OnGarotaOlhaEventHandler(object sender, EventArgs e);
   public delegate void OnPensarEmAlgoEventHandler(object sender, PensamentosEventArgs e);
   
   public partial class LeoVirtual
   {
	   #region Eventos
	   public event OnGarotaOlhaEventHandler OnGarotaOlha;
	   public event OnPensarEmAlgoEventHandler OnPensarEmAlgo; 
	   #endregion

	   #region Métodos
	   public void PaquerarGata()
	   { 
		   //Algum processamento aqui...
		   if (OnGarotaOlha != null)
		   {
			   OnGarotaOlha(this, new EventArgs());
		   }
		   //Algum processamento acolá...
	   }

	   public void PensarEmAlgo()
	   { 
		   //Criando os argumentos do evento:
		   PensamentosEventArgs e = new PensamentosEventArgs("SEXO", true);
		   
		   if (OnPensarEmAlgo != null)
		   {
			   OnPensarEmAlgo(this, e);
		   }
		   
		   //Depois do processamento ser feito fora da classe...
		   if (e.SeguirEmFrente.Equals(false))
		   {
			   throw new Exception(":-(");
		   }
	   }
	   #endregion
   }
}

Criamos uma classe chamada PensamentosEventArgs, derivada de EventArgs, que tem como campos duas variáveis.

Em segida, declaramos dois delegates e que em um deles, como parâmetros do evento utilizamos a classe PensamentosEventArgs.

Dentro da classe LeoVirtual, temos a declaração dos eventos OnGarotaOlha e OnPensarEmAlgo.

No método PaquerarGata, caso a propriedade OnGarotaOlha esteja apontando para algum método em um objeto que instancie a classe LeoVirtual, este método será executado através do ponteiro OnGarotaOlha, passando a instância da classe LeoVirtual e uma nova instância da classe base EventArgs.

No método PensarEmAlgo, primeiro instanciamos uma nova classe PensamentosEventArgs com alguns parâmetros. Caso o ponteiro OnPensarEmAlgo não for nulo, o método apontado será executado, e após a execução, verificamos se o valor da propriedade SeguirEmFrente da variável de argumentos do evento for false, disparamos uma exeption.

Sim, o EventArgs serve justamente para verificarmos e alterarmos propriedades do objeto no evento em questão. Só que para fazer isso, devemos criar uma classe herdada de EventArgs, pois ela nua e crua não serve para muita coisa, é mais para seguir as convenções de declaração de eventos.

Só para termos um exemplo prático, olhe o argumento do evento OnRowDataBound de um Gridview :-)

Façam o download do exemplo, brinquem com ele, e vocês não terão mais dúvidas de que Eventos não são um bicho de sete cabeças! E para o artigo ficar melhor entendido também :-)

Exemplo de Eventos em C# (53 KB)

Abraços e até mais!

Leonel Fraga de Oliveira Leonel Fraga de Oliveira é formado em Processamento de Dados na Faculdade de Tecnologia de São Paulo (FATEC-SP - 2002) e anteriormente em Técnico em Eletrônica, pela ETE Professor Aprígio Gonzaga (lá em 1999).
Atualmente trabalha como Analista de Sistemas na Prefeitura Municipal de São Caetano do Sul - SP
Tem como hobbies DJing (também trabalha como DJ freelancer) e ciclismo, além da manutenção dos sites NeoMatrix Light e NeoMatrix Tech.
Gosta de música eletrônica, tecnologia, cinema (super fã de Jornada nas Estrelas), gastronomia e outras coisas mais.


Compartilhe nas redes sociais

   

Deixe seu comentário

comments powered by Disqus