Desenvolvimento Multicamadas em Csharp (C#(csharp)) - Parte FINAL - Exemplo prático

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (20)  (1)

Neste último artigo vamos criar a classe que representa a lógica de negócio e a respectiva camada de apresentação para as informações sobre sinistros, ou seja, será adicionada a classe: clnSinistros.

Desenvolvendo uma aplicação Multicamadas para Windows em C#

Parte Final)

Introdução


Bom. :-) Saudações aos amigos que chegaram até aqui. Agradeço aos que adicionaram os meus artigos como seus favoritos, pois me motivaram a escrever mais. Gostaria de fazer apenas um pequeno esclarecimento antes de iniciar esta última parte.

Gosto de escrever e não tenho intenção em cobrar por meus artigos aqui no devmedia, não tenho nada contra aos posts pagos, ao contrátio, acho importante que as pessoas recebam pelo trabalho que fazem. Porém o meu objetivo é compartilhar conhecimento, trocar experiências e aprender com os demais colegas de profissão que comungam da mesma idéia. Sempre compro posts dos meus autores favoritos. Mas acho que em parte limitam essa minha intenção. O importante é que mais pessoas comecem a escrever e descobrir o quanto esta comunidade colabora com suas dúvidas e principalmente críticas construtivas. Isto só contribui para os meus conhecimentos e aprendizado de todos. Feito a observação. Vamos a parte final.

Este artigo é o último de uma série de sete artigos que apresentaram ao longo deste úmtimo mês um exemplo prático e simples abordando o desenvolvimento em camadas em C#.

No artigo passado, número seis, criamos as classes de negócio que clnApolices e clnParcelas, além dos formulários que compõem a camada de apresentação.

Veja novamente a Figura 1 - Diagrama ER Numerado.

Figura 1 - Diagrama ER Numerado



Relembrando:


A tabela de apólices é sem dúvida a mais importante do Sistema e para que possa ser feito o cadastro de uma nova apólice inicialmente temos que possuir dados nas tabelas de clientes (tbCliente), não está numerada pois nos artigos anteriores implementamos sua funcionalidade. Precisamos ter os dados já cadastrados na tabela de modelo de carros (tbModelo) [6] e a partir da apólice gerar as parcelas [5] para o pagamento por parte do cliente.

Já em relação aos sinistros ocorridos [2] para que possa ser cadastrado, inicialmente temos que ter a apólice cadastrada [1] e termos também previamente cadastrados os tipos de danos [3] e os tipos de sinistros já cadastrados.

Neste último artigo vamos criar a classe que representa a lógica de negócio e a respectiva camada de apresentação para as informações sobre sinistros, ou seja, será adicionada a classe: clnSinistros.

Também adicionaremos um formulário de splash e um formulário principal na camada de apresentação.

Mão na Massa:


1) Com o aplicativo aberto adicione uma nova classe chamada clnSinistros.cs.



2) Abaixo código da classe clnSinistro.cs, se você tem acompanhado os artigos, não há funcionalidades difirentes das já implementadas.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace Seguros_OO.Camada_Intermediaria.Logica_Negocios
{
  public class clnSinistros
  {
  //1 - Campos privados a classe
  private int idSinistro;
  private DateTime dataSinistro;
  private int idTipo;
  private int idDano;
  private string descSinistro;

  //2 - propriedades, acesso aos campos privados
  public int IdSinistro
  {
  get { return idSinistro; }
  set { idSinistro = value; }
  }
  public DateTime DataSinistro
  {
  get { return dataSinistro; }
  set { dataSinistro = value; }
  }
  public int IdTipo
  {
  get { return idTipo; }
  set { idTipo = value; }
  }
  public int IdDano
  {
  get { return idDano; }
  set { idDano = value; }
  }
  public string DescSinistro
  {
  get { return descSinistro; }
  set { descSinistro = value; }
  }
  //3 - métodos da classe de Negócios (clnSinistro.cs)

 
  //3.1 Buscar dados cujo codigo foi especificado
  public void Buscar()
  {
  string csql;
  csql = "Select * From tbSinistro where idSinistro=" + idSinistro;
  DataSet ds;
  clsDados seguros = new clsDados();
  ds = seguros.RetornarDataSet(csql);
  if (ds.Tables[0].Rows.Count > 0)
  {
  Array dados = ds.Tables[0].Rows[0].ItemArray;
  idSinistro = Convert.ToInt16(dados.GetValue(0));
  dataSinistro = Convert.ToDateTime(dados.GetValue(1));
  descSinistro = Convert.ToString(dados.GetValue(2));
  idTipo = Convert.ToInt16(dados.GetValue(3));
  idDano = Convert.ToInt16(dados.GetValue(4));
  }
  }

  //3.2 Buscar o próximo Id Numerico para
  //inclusao de um novo sinistro.
  public int BuscarId()
  {
  string csql;
  csql = "Select Top 1 (idSinistro) From tbSinistro order by idSinistro desc";
  int IdBuscado;
  clsDados seguros = new clsDados();
  IdBuscado = seguros.RetornarIdNumerico(csql);
  return IdBuscado;
  }

  //3.3 Método para incluir um novo sinistro no
  //Banco de dados
  public void Gravar()
  {
  string vdatasinistro = dataSinistro.ToString("MM/dd/yyyy");
  StringBuilder csql = new StringBuilder();
  csql.Append("Insert into tbSinistro");
  csql.Append("(");
  csql.Append("idSinistro,");
  csql.Append("dataSinistro,");
  csql.Append("descSinistro,");
  csql.Append("idTipo,");
  csql.Append("idDano");
  csql.Append(") Values(");
  csql.Append(idSinistro);
  csql.Append(",'" + vdatasinistro + "',");
  csql.Append("'" + descSinistro + "',");
  csql.Append(idTipo + ",");
  csql.Append(idDano + ")");
  clsDados seguros = new clsDados();
  seguros.ExecutarComando(csql.ToString());
  }

  //3.4 Método para atualizar (alterar um registro)
  public void Atualizar()
  {
  string vdatasinistro = dataSinistro.ToString("MM/dd/yyyy");
  StringBuilder csql = new StringBuilder();
  csql.Append("Update tbSinistro ");
  csql.Append("set idSinistro=");
  csql.Append(idSinistro);
  csql.Append(", dataSinistro='");
  csql.Append(vdatasinistro);
  csql.Append("', descSinistro='");
  csql.Append(descSinistro);
  csql.Append("', idTipo=");
  csql.Append(idTipo);
  csql.Append(", idDano=");
  csql.Append(idDano);
  csql.Append(" where idSinistro=");
  csql.Append(idSinistro);
  clsDados seguros = new clsDados();
  seguros.ExecutarComando(csql.ToString());
  }

  //3.5 Método para excluir um cliente do
  //Banco de dados
  public void Excluir()
  {
  StringBuilder csql = new StringBuilder();
  csql.Append("Delete From tbSinistro ");
  csql.Append(" where idSinistro=");
  csql.Append(idSinistro);
  clsDados seguros = new clsDados();
  seguros.ExecutarComando(csql.ToString());
  }
  }
}

3 ) Agora, alterne para a camada de apresentação, inclua um novo formulário com o nome FrmSinistro.cs.
 
Figura 2 - FrmSinistros.cs

4) Acrescente os controles no formulário e altere as propriedades conforme figura:

Figura 3 - Formulários (FrmSinistros)


5) Altere as propriedades de todos os botões para enabled = false.

6) Declare os namespace. Conforme abaixo:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Seguros_OO.Camada_Intermediaria.Logica_Negocios;

7) Inclua o método para limpar as caixas de textos.

  //Método público para limpar caixas de texto
  public void LimparTxt(Control controles)
  {
  foreach (Control ctl in controles.Controls)
  {
  if (ctl is TextBox) ctl.Text = "";
  }
  }

8) Acrescente um método publico sem retorno (void) chamado cancelar( ).

  private void cancelar()
  {
  groupBox2.Enabled = false;
  groupBox1.Enabled = true;
  txtidApolice.Text = "";
  txtidApolice.Enabled = true;
  txtidApolice.Focus();
  btnAtualizar.Enabled = false;
  btnIncluir.Enabled = false;
  btnExcluir.Enabled = false;
  btnCancelar.Enabled = false;
  }

9) Evento para o formulário Load, assim que o formulário for carregado, realizaremos duas tarefas. Instanciamos o objeto dadosDanos a partir da classe clnDanos( ) e o objeto dadosTipo a partir da classe clnTipos. Disparamos o método BuscarTodos( ) com a finalidade de “amarrar” os combos, ou seja, o usuário terá no campo visual o conteúdo do campo descDano e descTipo respectivamente, mas o valor di item são os dipostos na propriedade DisplayMember de cada uma. Abaixo código comentado.

  Private void FrmSinistros_Load(object sender, EventArgs e)
  {
  clnDanos dadosDanos = new clnDanos();
  clnTipos dadosTipo = new clnTipos();
  DataSet dsDanos = dadosDanos.BuscarTodos();
  DataSet dsTipos = dadosTipo.BuscarTodos();
  //amarrando os combos.
  //Exibindos descrições porém atrelamos o código
  //para gravação.
  cmbTipoDano.DataSource = dsDanos.Tables[0];
  cmbTipoDano.DisplayMember = “descDano”;
  cmbTipoDano.ValueMember= “idDano”;
  cmbTipoSinistro.DataSource = dsTipos.Tables[0];
  cmbTipoSinistro.DisplayMember = “descTipo”;
  cmbTipoSinistro.ValueMember = “idTipo”;
  }

10) Evento TexChanged do campo txtidApolice. Ao alterar o contéudo do campo, instanciamos o objeto apolice a partir da classe clnApolices( ) e o objeto cliente a partir da classe clnClientes. A finalidade do código é preencher os campos do tipo label.

  private void txtidApolice_TextChanged(object sender, EventArgs e)
  {
  clnApolices apolice = new clnApolices();
  if (txtidApolice.Text.Trim() == "")
  {
  lblnomeCli.Text = "";
  lbldescModelo.Text = "";
  return;
  }
  apolice.IdApolice = int.Parse(txtidApolice.Text);
  apolice.Buscar();
  clnClientes cliente = new clnClientes();
  cliente.IdCli = apolice.IdCli;
  cliente.Buscar();
  lblnomeCli.Text = cliente.NomeCli;
  clnModelos modelo = new clnModelos();
  modelo.IdModelo = apolice.IdModelo;
  modelo.Buscar();
  lbldescModelo.Text = modelo.DescModelo;
  if (lblnomeCli.Text == "")
  btnSinistro.Enabled = false;
  else
  btnSinistro.Enabled = true;
  }

11) Evento click do botão btnBuscar.

  private void btnBuscar_Click(object sender, EventArgs e)
  {
  FrmPesquisa f = new FrmPesquisa();
  f.Text = "Consulta dados das Apólices";
  f.Tag = "tbApolice"; //nome da tabela (macete) :)
  f.ShowDialog();
  }

12) Evento click do botão btnSinistro.

  private void btnSinistro_Click(object sender, EventArgs e)
  {
  groupBox2.Enabled = true;
  clnApolices apolice = new clnApolices();
  apolice.IdApolice = int.Parse(txtidApolice.Text);
  apolice.Buscar();
  if (apolice.IdSinistro != 0)
  {
  MessageBox.Show("Cliente já possui apólice, \n" +
  "Você só poderá alterar esses dados", "Aviso");
  clnSinistros sinistro = new clnSinistros();
  sinistro.IdSinistro = apolice.IdSinistro;
  sinistro.Buscar();
  txtidSinistro.Text = Convert.ToString(sinistro.IdSinistro);
  txtdataSinistro.Text = sinistro.DataSinistro.ToString("dd/MM/yyyy");
  txtdescSinistro.Text = sinistro.DescSinistro;
  clnDanos dano = new clnDanos();
  dano.IdDano = sinistro.IdDano;
  dano.Buscar();
  cmbTipoDano.Text = dano.DescDano;
  clnTipos tipo = new clnTipos();
  tipo.IdTipo = sinistro.IdTipo;
  tipo.Buscar();
  cmbTipoSinistro.Text = tipo.DescTipo;
  txtidSinistro.Enabled = false;
  txtdataSinistro.Focus();
  btnAtualizar.Enabled = true;
  btnIncluir.Enabled = false;
  btnExcluir.Enabled = true;
  btnCancelar.Enabled = true;
  }
  else
  {
  txtidSinistro.Text = "";
  txtdataSinistro.Text = "";
  txtdescSinistro.Text = "";
  txtidSinistro.Enabled = false;
  txtdataSinistro.Focus();
  btnAtualizar.Enabled = false;
  btnIncluir.Enabled = true;
  btnExcluir.Enabled = false;
  btnCancelar.Enabled = true;
  }
  groupBox1.Enabled = false;
  }

No código acima, vamos por parte. A primeira coisa que fizemos foi habilitar o groupbox2, conteiner onde se encontram os controles do cadastro de sinistros. Em seguida instanciamos um objeto apolice a partir da classe clnApolices( ), com a finalidade de verificar se houve sinistro para a apólice em questão. Se o valor do campo idSinistro for diferente de zero, indica que o cliente já possui apólice, sendo assim informamos ao mesmo que essa apólice só pode ser alterada, na verdade ela pode ser excluída, mas isso, não nos cabe orientá-lo (usuário do sistema). Instanciamos o objeto dano e o objeto tipo para alimentar os campos combo com a descrição do sinistro localizado. O restante do código já está bastante explorado.

13) Evento click do botão incluir.

  private void btnIncluir_Click(object sender, EventArgs e)
  {
  try
  {
  clnSinistros sinistro = new clnSinistros();
  sinistro.IdSinistro = sinistro.BuscarId();
  sinistro.DataSinistro = Convert.ToDateTime(txtdataSinistro.Text);
  sinistro.DescSinistro = txtdescSinistro.Text;
  sinistro.IdTipo = Convert.ToInt16(cmbTipoSinistro.SelectedValue);
  sinistro.IdDano = Convert.ToInt16(cmbTipoDano.SelectedValue);
  sinistro.Gravar();
  //atualizar a tabela de apólice com o número do sinistro
  //e checar a apolice para sinistrada.
  clnApolices apolice = new clnApolices();
  apolice.IdApolice = int.Parse(txtidApolice.Text);
  apolice.Buscar();
  apolice.SinistroApolice = true;
  apolice.IdSinistro = sinistro.IdSinistro;
  apolice.Atualizar();
  //mostra mensagem
  string mensagem = "Sinistro: " +
  sinistro.IdSinistro + "\nCliente: " + lblnomeCli.Text +
  "\nGravado com sucesso";
  MessageBox.Show(mensagem, "Sucesso",
  MessageBoxButtons.OK,
  MessageBoxIcon.Information);
  //chamar metodo cancelar (apenas desabilita os botões)
  cancelar();
  LimparTxt(groupBox2);
  }
  catch (Exception ex)
  {
  MessageBox.Show("Aconteu o erro: " + ex.Message, "Erro");
  }
  }

No código acima, também atualizamos a tabela de apólices com as informações da ocorrência de sinistro. Mais tarde alteraremos o código do botão btnVer no formulário de apólices que abrirá o formulário de sinistro para que possa ser verificado os dados do sinistro.

14) Evento do botão Atualizar.

  private void btnAtualizar_Click(object sender, EventArgs e)
  {
  try
  {
  clnSinistros sinistro = new clnSinistros();
  sinistro.IdSinistro= int.Parse(txtidSinistro.Text);
  sinistro.DataSinistro = Convert.ToDateTime(txtdataSinistro.Text);
  sinistro.DescSinistro = txtdescSinistro.Text;
  sinistro.IdTipo = Convert.ToInt16(cmbTipoSinistro.SelectedValue);
  sinistro.IdDano = Convert.ToInt16(cmbTipoDano.SelectedValue);
  sinistro.Atualizar();
  string mensagem = "Registro Sinsitro: " +
  sinistro.IdSinistro + "\nNome: " + lblnomeCli.Text +
  "\nAlterado com sucesso";
  MessageBox.Show(mensagem, "Sucesso",
  MessageBoxButtons.OK,
  MessageBoxIcon.Information);
  LimparTxt(groupBox2);
  cancelar();
  }
  catch (Exception ex)
  {
  MessageBox.Show("Aconteu o erro: " + ex.Message, "Erro");
  }
}

15) Evento do botão excluir.

  private void btnExcluir_Click(object sender, EventArgs e)
  {
  string pergunta;
  pergunta = "Deseja excluir o Sinistro: " +
  txtidSinistro.Text + ", do cliente: " + lblnomeCli.Text +
  "\ndo Cadastro Atual. ?" +
  "\n\n\nLembre-se essa ação deverá ocorrer " +
  "\nsomente em caso de ESTORNO";
  int ret = Convert.ToInt16(MessageBox.Show(pergunta, "Atenção",
  MessageBoxButtons.YesNo,
  MessageBoxIcon.Question));
  if (ret == 6)
  {
  //primeiro devemos fazer a atualização na
  //tabela de apolice.
  clnApolices apolice = new clnApolices();
  apolice.IdApolice = int.Parse(txtidApolice.Text);
  apolice.Buscar();
  apolice.SinistroApolice = false;
  apolice.IdSinistro = 0;
  apolice.Atualizar();
  //agora excluir da tabela de sinistro
  clnSinistros sinistro = new clnSinistros();
  sinistro.IdSinistro = int.Parse(txtidSinistro.Text);
  sinistro.Excluir();
  string mensagem = "Registro Sinistro: " +
  sinistro.IdSinistro + "\nNome: " + lblnomeCli.Text +
  "\nExcluído com sucesso";
  MessageBox.Show(mensagem, "Sucesso",
  MessageBoxButtons.OK,
  MessageBoxIcon.Information);
  LimparTxt(groupBox2);
  cancelar();
  }
  else
  {
  MessageBox.Show("Operação Cancelada",
  "Cancelada", MessageBoxButtons.OK,
  MessageBoxIcon.Information);
  }
  }

No código do evento excluir também atualizamos a tabela de apólices alterando os campos sinistroApolice para falso, indicando que não houve sinistro. Esta função deverá ser realizada no caso de estorno. Não é nossa intenção implementar outras regras para exclusão de sinistros, mas em um caso real, com certeza teria que ser ampliada estes conjunto de regras.

16) Evento do botão cancelar.

  private void btnCancelar_Click(object sender, EventArgs e)
  {
  LimparTxt(groupBox2);
  cancelar();
  }

17) Evento do botão procurar.

  private void btnProcurar_Click(object sender, EventArgs e)
  {
  FrmPesquisa f = new FrmPesquisa();
  f.Text = "Consulta Sinistros";
  f.Tag = "tbSinistro"; //nome da tabela (macete) :)
  f.ShowDialog();
  }

18) Evento do botão sair

  private void btnSair_Click(object sender, EventArgs e)
  {
  this.Close();
  }

19) Altere a propriedade modifiers do controle txtidApolice para public.

20) Agora alterne para o formulário de Apólices (FrmApolices.cs) para que possamos codificar o botão btnVer. Abaixo o código para o evento click do botão.

  private void btnVer_Click(object sender, EventArgs e)
  {
  FrmSinistros f = new FrmSinistros();
  f.txtidApolice.Text = this.txtidApolice.Text;
  f.ShowDialog();
  txtidApolice_Leave(sender, e); //método deve ser public
  }
 

Camada de Apresentação: Finalizando

A intenção aqui não é criar formulários cheios de detalhes, pelo contrário serão simples apenas para finalizar o nosso exemplo. Você poderá melhorá-los assim como todo o projeto.

FrmSplash.

 ) Adicione na Camada de Apresentação um novo Formulário do tipo splash chamado FrmSplash. Clique com o botão direito do mouse sobre o nome do projeto e escolha ADD >> New Item >> WindowsForm dê o nome FrmSplash.cs.

2) Altere as propriedades do formulário FrmSplash conforme abaixo:

• FormBorderStyle = none;
• Size = 553; 379

3) Coloque um controle picture e acrescente uma imagem de fundo com o tamanho acima.

Figura 4 - FrmSplash.cs


4) Adicione agora os seguintes controles:

• 01 progressbar;
• 01 timer.

Figura 5 - Controles Adicionados


Aqui, depois adicionaremos o código.

5 ) Agora acrescente um novo formulário chamado FrmPrincipal. Esse formulário deverá conter um menu conforme a figura.

Figura 6 - FrmPrincipal.cs


6) Altere a propriedade WindowState do formulário para Maximized.

Funcionamento:


Colocaremos o nosso projeto para ser iniciado pelo formulário de splash, e em três segundo será disparado o formulário principal, para que possamos acessar os formulários anteriormente criados.

1) Para isso no Solution Explorer dê um duplo clique no arquivo Program.cs para acessar essa classe e faça a alteração conforme abaixo:

2) Agora alterne para o formulário FrmSplash, defina a propriedade enabled do timer para true. Em seguida coloque o código abaixo para o evento.


  private void timer1_Tick(object sender, EventArgs e)
  {
  if (progressBar1.Value >= 100)
  {
  timer1.Enabled = false;
  FrmPrincipal f = new FrmPrincipal();
  this.Hide();
  f.ShowDialog();
  this.Close();
  }
  else
  {
  progressBar1.Value += 10;
  }
  }

3) Assim que a barra de progressão ter o seu valor maior ou igual a 100, o formulário é oculto (hide), disparamos o formulário principal, e quando este for fechado a aplicação será encerrada.

Para finalizar essa aplicação, basta acrescentar os códigos nos menus para chamar os formulários que criamos. Altere a propriedade IsMdiConteiner do FrmPrincipal para true, assim podemos acessar os formulários internos dentro do form principal. Veja a aparência até o momento.

 

Vou incluir a funcionalidade para chamar o cadastro de clientes. As demais, é só você seguir este exemplo:

  private void clientesToolStripMenuItem_Click(object sender, EventArgs e)
  {
  FrmClientes f = new FrmClientes();
  //indicamos que a janela pai é o form atual
  f.MdiParent = this;
  //Carregamos o formuladio dentro do form pai.
  f.Show();
  }

Conclusão:


Note que essa parte final, não tem uma “linda” aparência pois não era o intuito destes artigos, mas você com certeza consegue melhorar a aplicação como um todo.

 ncerramos aqui a série de artigos demonstrando um exemplo de Sistema de Controle de Apólices de Veículos, onde foram utilizados os conceitos de Orientação a Objetos e o desenvolvimento em n (3) camadas. Espero que tenham gostado. Aguardos os feedbacks. Muito obrigado pela paciência e pela ajuda que me deram.

Estou deixando disponibilizado o arquivo zipado, desse nosso exemplo. Até um próximo artigo. Vou demorar um pouquinho, pois o mestrado anda corrido. :-)

Contato pelo e-mail:  professormoraes_arroba_gmail.com


Marcos Roberto de Moraes
Mestrando em Educação
Esp. em Administração de Sist. De Informação
 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?