O NeoMatrix Tech está de casa nova!

Você deverá ser redirecionado em 6 segundos. Se não, visite:
http://www.leonelfraga.com/neomatrixtech
e atualize seus favoritos.

Aviso IMPORTANTÍSSIMO!

Aviso aos navegantes:

O NeoMatrix Tech mudou de casa!!!

A partir de agora, acessem pelo novo endereço:

http://www.leonelfraga.com/neomatrixtech

Ué... mas é só o domínio mudou de lugar?

R: Na verdade, não é bem assim hehe. Este domínio que você acessa agora aponta para um blog hospedado no Blogger, enquanto no novo, aponta para um blog na plataforma Wordpress, hospedagem própria, muito mais rápida e com um layout mais agradável de ler ;)

Não vou fechar este domínio igual ao que eu fiz com o NM Light (que já está 100% na nova plataforma). Talvez beeeeeeem depois eu faça isso.

Todos os posts daqui se encontram lá, e novos posts serão colocados somente no novo endereço.
A única coisa que não consegui importar foram os comentários. Mas em breve vai ter um post contando sobre a epopéia que foi migrar o NeoMatrix Tech!

Somente vou fechar a área de comentários daqui. Caso queiram comentar, favor ver o post correspondente no "Novo NeoMatrix Tech" e comentem por lá. É bem melhor! (pena que os permalinks "amigáveis para SEO" não funcionam lá, dá erro 404 e não consigo fazer a configuração funcionar. E olha que eu já vi vários artigos falando desse assunto :( ).

Quem assina o feed, já está lendo o conteúdo do novo NeoMatrix Tech!

sexta-feira, 2 de janeiro de 2009

Eventos em C# de maneira simples

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:

   1: public delegate void MeuDelegate(<tipo> parametro1, <tipo> 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:

   1: 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:

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

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

   1: public event <delegate> <nome 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:

   1: 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:

   1: private void AlgumaCoisa()
   2: {
   3:     ...
   4:     if(MeuManipuladorDeEvento != null)
   5:     {
   6:         MeuManipuladorDeEvento(this,new EventArgs());
   7:     }
   8:     ...
   9: }

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:

   1: public Classe1 MeuObjeto = new Classe1();
   2:  
   3: //Dentro do construtor de um form, por exemplo
   4: public Form1()
   5: {
   6:     InitializeComponent();
   7:  
   8:     //Atribuindo manualmente os manipuladores de evento
   9:     MeuObjeto.MeuEvento += new MinhaAssinaturaDeEventoEventHandler(MeuMetodo);
  10: }
  11:  
  12: public MeuMetodo(object sender, EventArgs e)
  13: {
  14:     //Faça o que tem que fazer...
  15: }

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:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4:  
   5: namespace MinhaClasseTeste
   6: {
   7:     #region Classe de argumentos de evento
   8:     public class PensamentosEventArgs : EventArgs
   9:     {
  10:         public string Pensamento = "";
  11:         public bool SeguirEmFrente = true;
  12:  
  13:         public PensamentosEventArgs()
  14:         { }
  15:  
  16:         public PensamentosEventArgs(string pPensamento, bool pSeguirEmFrente)
  17:         {
  18:             this.Pensamento = pPensamento;
  19:             this.SeguirEmFrente = pSeguirEmFrente;
  20:         }
  21:     }
  22:     #endregion
  23:  
  24:     public delegate void OnGarotaOlhaEventHandler(object sender, EventArgs e);
  25:     public delegate void OnPensarEmAlgoEventHandler(object sender, PensamentosEventArgs e);
  26:     
  27:     public partial class LeoVirtual
  28:     {
  29:         #region Eventos
  30:         public event OnGarotaOlhaEventHandler OnGarotaOlha;
  31:         public event OnPensarEmAlgoEventHandler OnPensarEmAlgo; 
  32:         #endregion
  33:  
  34:         #region Métodos
  35:         public void PaquerarGata()
  36:         { 
  37:             //Algum processamento aqui...
  38:             if (OnGarotaOlha != null)
  39:             {
  40:                 OnGarotaOlha(this, new EventArgs());
  41:             }
  42:             //Algum processamento acolá...
  43:         }
  44:  
  45:         public void PensarEmAlgo()
  46:         { 
  47:             //Criando os argumentos do evento:
  48:             PensamentosEventArgs e = new PensamentosEventArgs("SEXO", true);
  49:             
  50:             if (OnPensarEmAlgo != null)
  51:             {
  52:                 OnPensarEmAlgo(this, e);
  53:             }
  54:             
  55:             //Depois do processamento ser feito fora da classe...
  56:             if (e.SeguirEmFrente.Equals(false))
  57:             {
  58:                 throw new Exception(":-(");
  59:             }
  60:         }
  61:         #endregion
  62:     }
  63: }

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!

0 comentários:


Postar um comentário

Para tornar este artigo ainda mais interessante, escreva suas críticas (desde que construtivas e sem ofenças), elogios, sugestões, complementos, dúvidas, etc, etc, etc!!!

  © Blogger templates ProBlogger Template by Ourblogtemplates.com 2008 - Editado e configurado por Leonel F.

Voltar ao TOPO