C# - Como fazer uma classe definir e disparar eventos
Neste artigo veremos como fazer uma classe definir e disparar eventos na linguagem C#. |
Vamos começar definindo o que são eventos e como eles se comportam. Os eventos na plataforma .NET são baseados no modelo de delegate.
Um evento é uma mensagem enviada por um objeto para sinalizar a ocorrência de uma ação.
A ação pode ser causada pela interação do usuário, como o clique em um botão, ou pode ser acionada por alguma outra lógica de programa, como a alteração do valor de uma propriedade.
O objeto que aciona o evento é chamado de remetente(sender) do evento. O remetente do evento não sabe qual objeto ou método receberá (handle) os eventos que ele aciona. O evento normalmente é membro do remetente(sender) do evento.
Para definir um evento usamos a palavra-chave event, e, para acionar um evento adicionamos um método que é marcado como protected e virtual; damos a esse método o nome On+NomeEvento. Ex: OnPrinting().
O método deve usar um parâmetro que especifique um objeto de dados de evento. Você fornece esse método para permitir que as classes derivadas substituam a lógica para acionar o evento. Uma classe derivada sempre deve chamar o método OnNomeEvento da classe base a fim de garantir que os delegates registrados recebam o evento.
Definindo e disparando eventos em uma classe
Para mostrar como definir e disparar eventos em uma classe vamos usar como exemplo uma classe Conta que gerencia uma conta bancária.
Se o programa tentar remover um valor maior do que o saldo atual da conta, o objeto Conta vai gerar um evento OnSaldoInsuficiente que incluir dois parâmetros:
O objeto SaldoInsuficienteArgs inclui duas propriedades úteis :
Para poder fazer a implementação do evento e seu tratamento na classe vamos realizar as seguints tarefas:
Com o roteiro definido vamos ver isso funcionando na prática.
Criando o projeto Windows Forms
Vamos criar um vou criar um projeto Windows Desktop usando o template Windows Forms App(.NET Framework) usando o VS 2017 Community com o nome WF_ClasseEventos;
A partir da ToolBox inclua no formulário Form1.cs os controles:
Este´será o formulário usado no projeto. Bem simples.
Definir a classe SaldoInsuficienteArgs
A classe SaldoInsuficienteArgs deve conter dois campos : ValorDebito e Libera, e, deve herdar da classe EventArgs que representa a classe base das classes que contêm dados de evento e fornece um valor a ser usado para eventos que não incluem dados de evento.
using System;
namespace WF_ClasseEventos { public class SaldoInsuficienteArgs : EventArgs { // O valor a ser debitado public decimal ValorDebito; //Define se libera ou não o debito do valor // O valor padrão é false para não permitir saldo negativo public bool Libera = false; } } |
Esta classe
fornece o campo ValorDebito que representa o valor
do débito que será sacado da conta. O campo Boolean
Libera permite que o programa principal diga ao
objeto se ele deve permitir o débito, mesmo que isso faça com que a conta fique
com um saldo negativo.
Observe que a classe
SaldoInsuficienteArgs
não inclui o
saldo atual da conta. O programa principal pode obter isso do próprio objeto
Conta.
Agora vamos criar a classe Conta no projeto via menu Project-> Add Class e nesta classe vamos definir:
using System;
namespace WF_ClasseEventos
{
public class Conta
{
public event EventHandler<SaldoInsuficienteArgs> SaldoInsuficiente;
// O saldo da conta
public decimal Saldo { get; set; }
// Retirar uma quantidade da conta
public void Debito(decimal valor)
{
if (valor < 0)
{
throw new ArgumentOutOfRangeException("O valor do débito deve ser um valor positivo.");
}
// Verifica se existe saldo
if (Saldo >= valor)
{
// Há saldo
Saldo -= valor;
}
else
{
// Não tem dinheiro suficiente
// Dispera o evento SaldoInsuficiente
if (SaldoInsuficiente != null)
{
// Cria um objeto do tipo SaldoInsuficienteArgs
SaldoInsuficienteArgs args = new SaldoInsuficienteArgs();
args.ValorDebito = valor;
// Dispara o evento somente se houver inscritos
SaldoInsuficiente?.Invoke(this, args);
// Se for liberado
// debita o valor valor e a conta fica negativa
if (args.Libera)
{
Saldo -= valor;
}
}
}
}
// Deposita valor na conta
public void Credito(decimal valor)
{
if (valor < 0)
{
throw new ArgumentOutOfRangeException("O valor do crédito deve ser um valor positivo.");
}
Saldo += valor;
}
}
}
|
Na classe conta definimos o evento SaldoInsuficiente usando um delegate. Este evento deve ser manipulado por um manipulador de eventos que usa dois parâmetros:
public event EventHandler<SaldoInsuficienteArgs> SaldoInsuficiente;
Aqui estamos usando o delegate EventHandler predefinido para definir o evento.
O código usa também ArgumentOutOfRangeException que é uma exceção que é gerada quando o valor de um argumento está fora do intervalo permitido de valores conforme definido pelo método invocado.
Disparando o Evento
Após definir o evento temos no método Debito o disparo do evento .
Primeiro, o
método verifica se o montante a ser debitado é menor que zero e lança uma
exceção, se for.
Em seguida, o método verifica o saldo da conta. Se o saldo for grande o
suficiente para cobrir o débito, o método subtrai o saldo.
Se o saldo for insuficiente, o método gera o evento
SaldoInsuficiente.
A instrução if (SaldoInsuficiente! = Null) verifica se algum código se inscreveu no evento. É uma sintaxe estranha, mas se não houver manipuladores de eventos registrados para o evento, o SaldoInsuficiente será nulo, então o método não precisa disparar o evento.
De fato, se
ele tentar levantar o evento, ele receberá uma exceção
“Referência de objeto não definida para uma instância de um objeto”.
Se um manipulador de eventos estiver inscrito no evento, o método criará um
objeto SaldoInsuficienteArgs e definirá seu
ValorDebito. Em seguida, ele usa a sintaxe
SaldoInsuficiente(this, args) para disparar o
evento, passando o objeto atual e o objeto
SaldoInsuficienteArgs para os manipuladores de eventos inscritos.
Quando os manipuladores de eventos retornam, o método verifica o valor
Libera do objeto
SaldoInsuficienteArgs para ver se ele deve debitar a conta mesmo assim.
Se Libera for true, o
método subtrai o valor do débito do saldo atual.
Inscrevendo-se no Evento
No formulário Form1 vamos usar o evento Load para criar uma instância da classe Conta, fazer uma inicialização do saldo com um valor igual a 100 , exibir o valor e a seguir fazer a inscrição no evento SaldoInsuficiente:
// Define obeto do tipo Conta private Conta ContaBancaria; private void Form1_Load(object sender, EventArgs e) { //Cria novo objeto do tipo conta e define o saldo ContaBancaria = new Conta(); ContaBancaria.Saldo = 100m; //exibe o valor do saldo txtSaldo.Text = ContaBancaria.Saldo.ToString("C"); // Inscrever-se no evento SaldoInsuficiente
ContaBancaria.SaldoInsuficiente += Conta_SaldoInsuficiente;
}
|
Fazer o tratamento do evento
Vamos definir o código que será executado quando o objeto Conta dispara o evento SaldoInsuficiente, para isso temos que incluir o código abaixo no método Conta_SaldoInsuficiente:
// Trata o evento SaldoInsuficinte da conta private void Conta_SaldoInsuficiente(object sender, SaldoInsuficienteArgs e) { // Cria um objeto do tipo Conta Conta conta = sender as Conta; // Pergunta se permite a transação
if (MessageBox.Show("Saldo Insuficiente.\n\n Saldo Atual: " +
conta.Saldo.ToString("C") + "\n Valor Débito: " + e.ValorDebito.ToString("C") + "\n\n" +
"Deseja permitir esta transação ?",
"Permite ?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
// Permite o debito
e.Libera = true;
}
}
|
Este método
converte o parâmetro do remetente(sender) em um
objeto Conta.
Em seguida, o manipulador de eventos exibe uma caixa de mensagem que fornece
informações sobre a transação e pergunta ao usuário se deve permitir a
transação.
Se o usuário clicar em Sim, o código define o campo Libera do objeto SaldoInsuficienteArgs como true, de modo que o objeto Conta que gerou o evento sabe que deve permitir a transação.
Executando o projeto iremos obter:
Pegue o código do projeto aqui : WF_ClasseEventos.zip
"Por que estás abatida, ó minha alma, e por que te
perturbas dentro de mim? Espera em Deus, pois ainda o louvarei, o qual é a
salvação da minha face, e o meu Deus."
Salmos 42:11
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
C# - Entendo o I/O na plataforma .NET - Macoratti
C# - Lendo e escrevendo em arquivos textos e binários - Macoratti.net
LINQ- Mesclando dois arquivos distintos e agrupando ... - Macoratti
C# - Combinando Imagens - Macoratti.net
VB .NET - Mesclando e imprimindo imagens - Macoratti
C# - Bloqueando Pastas - Macoratti
C# - Exibindo imagens de uma pasta - Macoratti