VB .NET - Curso Prático ADO .NET - Desenvolvendo uma aplicação : Definindo o código da Interface - IX


Nesta aula do curso prático iremos definir o fluxo de funcionamento da aplicação bem como definir a estratégia de utilização do código nos eventos dos controles do formulário de forma a termos uma aplicação funcional.

Até o momento temos criado uma solução no Visual Studio 2012 Express for desktop e um projeto Windows Forms CiaFilmesWin que contém um arquivo App.Config e 4 formulários.

O que irá ocorrer se executarmos o projeto neste momento ?

Sabemos que o formulário frmLogin será executado e apresentado ao usuário visto que na janela de propriedades do projeto a opção Startup Form define este formulário como formulário inicial da aplicação.

Então veremos o formulário de login conforme a figura abaixo:

Temos 4 botões de comando neste formulário mas se clicarmos em qualquer um deles nada vai acontecer. Ou seja temos apenas um formulário sem nenhuma ação definida ou código que defina uma ação a ser realizada.

O fluxo de funcionamento deste formulário deverá ser o seguinte:

Como podemos então 'dar vida' a este formulário e como podemos incluir código que acione os demais formulários do projeto ?

Uma das formas mais simples de fazer isso é utilizar os eventos dos controles nos formulários. Cada controle Windows Forms possui dezenas de eventos e podemos escolher o mais apropriado à ação do usuário e atribuir o código que irá realizar a ação que desejamos que ocorre quando o evento ocorrer.

Os eventos de cada controle podem ser vistos na janela de propriedades do controle. Para isso selecione o controle e pressione F4. A seguir clique no ícone de eventos para exibir os eventos do controle. Abaixo vemos os eventos para o controle Button - Submeter :

O evento Click ocorre quando o componente for clicado e é o evento apropriado ao nosso caso. Para incluir o código neste evento clique duas vezes sobre o controle ou sobre o evento Click exibido na janela de propriedades do controle.

Será aberto a janela de código do formulário exibindo o código que trata o evento Click do botão :

Public Class frmLogin
    Private Sub btnSubmeter_Click(sender As Object, e As EventArgs) Handles btnSubmeter.Click
    End Sub
End Class

Observe que o código do evento Click esta definido na classe frmLogin que é a classe do nosso formulário frmlogin.

Como não temos nenhum código atribuído ao tratamento do evento nada esta ocorrendo. A ação que queremos disparar é a abertura do formulário frmPesquisas. Para isso vamos incluir a seguinte linha de código no tratamento do evento:

Public Class frmLogin

    Private Sub btnSubmeter_Click(sender As Object, e As EventArgs) Handles btnSubmeter.Click
       My.Forms.frmPesquisas.ShowDialog()
    End Sub

End Class

A linha de código My.Forms.frmPesquisas.ShowDialog() deverá abrir o formulário frmPesquisas quando o controle for clicado.

Vamos entender o código:

Estamos usando o namespace My do Visual Studio 2012. O namespace My expõe propriedades e métodos que permitem que você facilmente aproveite o poder do .NET Framework. O namespace My simplifica problemas comuns de programação, reduzindo frequentemente uma tarefa difícil para uma única linha de código.

Além disso, o namespace My é totalmente extensível para que você possa personalizar o comportamento de My e adicionar novos serviços à sua hierarquia para adaptar-se às necessidades de aplicativos específicos.

Namespaces organizam os objetos em um assembly ; assim, um assembly podem conter um ou mais namespaces , e estes namespaces pode conter um ou mais namespaces. Desta forma os Namespaces evitam a ambiguitdade e organizam referências quando são usados grande grupos de objetos como as librarys de classes.

O namespace raiz , ou seja, aquele que esta no topo da 'hierarquia' é o System ; dentro do namespace raiz System temos algo em torno de 100 classes que representam todo os tipos de dados.

A classe system contém outras classes que realizam outros serviços. Dentro do NameSpace System temos , mais ou menos 24 sub-niveis de namespaces.

O namespace My veio reunir algumas das funções mais utilizadas no .NET Framework, expor novas funções que antes só poderiam ser utilizadas através de APIs, ou até mesmo facilitar o uso de outras funções. O objetivo é ganhar produtividade obtendo as informações de forma mais rápida. Abaixo as principais classes e suas descrições do namespace My:

Application Sistemas e serviços
Computer Computador Host e serviços
Forms Formulários do projeto atual
Resources Recursos
Settings parâmetros do sistema e do usuário
Users segurança do usuário

O objeto My.Forms fornece uma instância de cada formulário no projeto atual, o nome da propriedade é o mesmo que o nome do formulário que a acessa a propriedade.

No código estamos usando a classe Forms seguida do formulário que desejamos abrir: frmPesquisas e do método para abrir o formulário, no caso ShowDialog():

O método ShowDialog() mostra o formulário como uma caixa de diálogo modal e obrigará o usuário a fechar o formulário para continuar a execução do código.

Poderíamos ter usado o método Show() que mostra o formulário como uma caixa de diálogo não-modal que não obrigará o usuário fechar o formulário. Resumindo:

Então para completar as ações vinculadas aos eventos Click de cada um dos demais botões do nosso formulário vamos completar cada tratamento de evento com o código que usa o namespace My.Forms e o respectivo formulário que já criamos. Assim teremos o seguinte código:

Public Class frmLogin

    Private Sub btnSubmeter_Click(sender As Object, e As EventArgs) Handles btnSubmeter.Click
        My.Forms.frmPesquisas.ShowDialog()
    End Sub

    Private Sub btnPesquisar_Click(sender As Object, e As EventArgs) Handles btnPesquisar.Click
        My.Forms.frmPesquisas.ShowDialog()
    End Sub

    Private Sub btnRegistrar_Click(sender As Object, e As EventArgs) Handles btnRegistrar.Click
        My.Forms.frmRegistros.ShowDialog()
    End Sub

    Private Sub btnEncerrar_Click(sender As Object, e As EventArgs) Handles btnEncerrar.Click
        Me.Close()
    End Sub
End Class
Uma outra forma de abrir um formulário sem usar o recurso My.Forms pode ser feita assim:
  1. Declare uma variável do tipo do formulário que desejamos abrir

Dim ofrmPesquisa as FrmPesquisas

  1. Crie uma instância da variável

ofrmPesquisa = new FrmPesquisas

  1. Use a instância criada com o método apropriado : Show() ou ShowDialog() para abrir o formulário:

ofrmPesquisa.Show()

ou

Dim ofrmPesquisa As New frmPesquisas
ofrmPesquisa.ShowDialog()

Observe que no evento Click do botão Encerrar usamos o código Me.Close(), onde o método Close() fecha o formulário atual.

A palavra chave Me é utilizada para obter a referência ao tipo Atual. O método Close() fecha a instância do formulário atual.

O código acima permite que ao clicarmos em cada botão de comando o respectivo formulário seja aberto e nada mais. Vamos então definir uma estratégia para o código que devemos incluir no nosso projeto para que o mesmo funcione.

Abaixo temos uma figura que esquematiza as ações associadas aos eventos dos botões de comando mostrando uma visão geral do fluxo de funcionamento básico do nosso projeto.

Vamos definir o código de cada um dos eventos dos controles dos formulários com mais detalhes tomando como base o fluxo estabelecido.

Criando o módulo Geral

Antes de definir o código do formulário vamos criar um módulo no projeto. No menu PROJECT clique em Add Module, informe o nome Geral.vb e clique no botão Add.

A seguir defina o seguinte código neste módulo.

Module Geral

    'variaveis e métodos publicos (visiveis em todo o projeto)
    Public strConexaoSQLServer As String = Nothing
    Public clienteLogin As String
    Public clienteCodigo As Integer

    Public Function CifraDecifraSenha(Text As String) As String
        Dim strTempChar As String = ""

        For i = 1 To Len(Text)
            If Asc(Mid$(Text, i, 1)) < 128 Then
                strTempChar = Asc(Mid$(Text, i, 1)) + 128
            ElseIf Asc(Mid$(Text, i, 1)) > 128 Then
                strTempChar = Asc(Mid$(Text, i, 1)) - 128
            End If
            Mid$(Text, i, 1) = Chr(strTempChar)
        Next i
        CifraDecifraSenha = Text
    End Function
End Module

Mas porque criamos esse módulo e qual o nosso objetivo ?

Você usa um módulo para criar um container para variáveis, procedimentos e funções usadas em toda a aplicação , e, em alguns casos, para fornecer o método que funciona como um ponto de entrada para a aplicação.

Sintaticamente falando , um bloco de módulo esta delimitado pelas palavras chaves Module e End Module e podem conter constantes públicas ou privadas, campos, propriedades e métodos.

Os módulos da linguagem Visual Basic fornecem uma maneira simples de testar pequenos trechos de códigos. Em aplicações de produção os módulos são menos usados do que as classes mas não deixam de ter sua utilidade para ilustrar conceitos importantes.

No nosso exemplo as variáveis strConexaoSQLServer, clienteLogin e clienteCodigo e a função CifraDecifraSenha() a serão visíveis em todo o projeto.

Não é uma boa prática usar variáveis públicas em uma aplicação orientada a objetos visto que estamos quebrando uma das características principais do paradigma que é o encapsulamento.

1- Definindo o código do formulário de Login - Botão Submeter - evento btnSubmeter_Click

No evento Click do botão Submeter temos que verificar se as credenciais de Login e Senha informadas pelo usuário são válidas para abrir o formulário de pesquisas.

Para verificar as credencias de Login e Senha teremos que acessar o banco de dados CiaFIlmes recuperar informações da tabela Clientes e verificar se o login e senha informados conferem com os dados gravados nos campos senha e login desta tabela.

Como as nossas informações estão gravadas em um banco de dados SQL Server temos que usar os provedores de dados ADO .NET para o SQL Server e as classes que permitem o acesso ao banco de dados SQL Server.

As classes que permitem isso estão nos namespaces:

  1. System.Data -
  2. System.Data.SqlClient.

Portanto teremos que declarar estes namespaces no formulário de login, no início do formulário:

Imports System.Data
Imports System.Data.SqlClient

Para acessarmos o banco de dados precisamos definir a string de conexão. A string de conexão contém a informação necessária para que o sistema possa localizar o banco de dados e realizar a abertura de uma conexão para que as informações sejam recuperadas da tabela Clientes.

Mas como eu sei qual é a string de conexão correta ?

A forma mais simples é abrir o banco de dados no SQL Server LocalDB na janela DataBase Explorer e pressionar a tecla F4 e na janela de propriedades localizar o item Connection e a seguir Connection String:

Podemos inclusive copiar a string de conexão que no exemplo esta definida como:
Data Source=(LocalDB)\v11.0;Initial Catalog=CiaFilmes;Integrated Security=True

Eu poderia definir uma variável do tipo string e atribuir a esta variável o valor da string de conexão acima mas isso não é muito recomendado. Um bom lugar para guardar esta informação e no arquivo App.Config da aplicação.

Vamos então abrir o arquivo App.Config e armazenar neste arquivo a string de conexão para acesso ao banco de dados. Veja abaixo o arquivo já com a inclusão destacada em azul:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <connectionStrings>
    <add name="conexaoSQLServerLocalDB" providerName="System.Data.sqlclient" connectionString="Data Source=(LocalDB)\v11.0;
Initial Catalog=CiaFilmes;Integrated Security=True" />

  </connectionStrings>
</configuration>

No interior da seção <configuration> eu inclui a seção <connectionStrings> definindo os seguintes valores:

Já resolvemos o problema de onde armazenar a string de conexão mas e agora como iremos obter o valor da string de conexão ?

A leitura da string de conexão armazenada no arquivo App.Config é feito pela classe ConfigurationManager.ConnectionStrings("nome_da_Conexao").ToString().

Para usar essa classe teremos que incluir no projeto uma referência ao namespace System.Configuration.

Então clique no menu PROJECT-> Add Reference marque o item Assemblies->Framework e selecione System.Configuration clicando no botão OK:

Feito isso basta incluir no início do formulário junto com os demais namespaces a declaração Imports System.Configuration.

Vamos agora colocar o código para ler a string de conexão no arquivo App.Config quando o formulário frmLogin for carregado. Isso ocorre no evento Load e é um dos primeiros eventos que ocorre na carga inicial do formulário.

Para acionar o tratamento do evento frmLogin_Load abra o formulário e clique duas vezes sobre ele; a seguir inclua o código abaixo:

Private Sub frmLogin_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        strConexaoSQLServer = ConfigurationManager.ConnectionStrings("conexaoSQLServerLocalDB").ToString()
    End Sub

O código lê o valor da string de conexão e atribui este valor a uma variável chamada strConexao. Mas onde declaramos esta variável ?

O Intellisense do Visual Studio deve estar marcando a variável com um erro do tipo: 'strConeao' is not declared.It may be inacessible due to its protection level"

Lembre-se sempre que uma variável deve ser sempre declarada antes de ser usada. A mensagem alerta que ela ou não foi declarada ou foi declarada mas esta inacessível. Como assim ???

 Variáveis
O conceito de variável é fundamental em qualquer linguagem de programação , portanto , não poderia ser diferente com o VB.NET.

O que é uma variável ? ( bem ai vareia !!! ) . Podemos dizer que variável é um lugar que usamos para armazenar uma informação que pode sofrer alteração durante a execução de um programa.

As variáveis são usadas para guardar valores que serão usados durante o decorrer do programa , para guardar informações fornecidas pelo usuário e que será exibida mais tarde. 

Cada variável que usamos é identificada por um nome e por um tipo.

Você pode guardar informação de diversos tipos em uma variável :  números pequenos , números médios , números grandes ,  letras , palavras , frases , páginas de texto , etc...; Então dizemos que uma variável tem um nome que a identifica e um tipo de dado que esta armazenando. Quando você guarda uma informação em uma variável esta usando a memória do computador para isto , e , quanto maior a informação que você guardar mais memória você vai  gastar dependendo do tipo de variável que decidir usar.

Se você precisar realizar cálculos que envolvam somente valores inteiros deverá procurar usar uma variável do tipo Integer , você pode usar uma variável do tipo Long , Single e Double mas com isto irá gastar mais memória.

Podemos criar três tipos básicos de variáveis no VB.NET :
- Variáveis simples -  usadas para guardar valores simples como números e strings(alfanuméricas)
- Variáveis complexas - usadas para guardar valores mais complexos , vetores , e tipos definidos pelo usuário
- Variáveis objeto - usadas para guardar variáveis objeto

Para declarar uma variável temos que definir um nome para a variável, um tipo e opcionalmente atribuir um valor inicial. No Visual Basic usamos a palavra reservada Dim (Dimension) para declarar variáveis.

Assim podemos declarar variáveis usando a seguinte sintaxe:

Dim nome As String
Dim idade As Integer
Dim valor As Double = 0
Dim conexao As String = nothing
Dim dataNascimento As Date = "15/03/1978"
Dim oTeste As Object = nothing

No VB .NET podemos declarar múltiplas variáveis em uma única linha:

Dim a , b , c AS String

Dim X As integer = 1 , Y AS String = "COPA" , Z AS Integer = 2002

Além disso o Visual Basic .NET trouxe um novo escopo para as variáveis: o escopo a nível de blocos.

Assim no VB.NET quando você declara uma variável dentro de um bloco de código : FOR...NEXT , DO WHILE , IF..THEN , SELECT...CASE , TRY ... CATCH, etc... ela deixa de existir fora do bloco de código onde foi declarada.

Quanto ao nome da variável para não complicar você deve procurar usar nomes que identificam claramente o que a variável representa. Veja exemplos comparando

Dim id As integer (pior)
Dim Idade As Integer (melhor)
Dim vlrpagseg As Double (pior)
Dim valorPagamentoSeguro As Double (melhor)

No nosso código como queremos que a variável strConexaoSQLServer seja visível em todo o formulário vamos declará-la no início do formulário:

Dim strConexaoSQLServer As String = Nothing

Agora no evento Click do botão Submeter iremos primeiro verificar se o cliente informou as credenciais corretamente. Veja como ficou o código:

 Private Sub btnSubmeter_Click(sender As Object, e As EventArgs) Handles btnSubmeter.Click

        If String.IsNullOrEmpty(txtLogin.Text) Or txtLogin.Text.Length < 5 Then
            MessageBox.Show("Informe um Login válido !", "Login", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtLogin.Focus()
            Return
        End If
        If String.IsNullOrEmpty(txtSenha.Text) Or txtSenha.Text.Length < 5 Then
            MessageBox.Show("Informe uma senha válida !", "Senha", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtSenha.Focus()
            Return
        End If
End Sub

Entendo o código:

  1. Verificamos se o usuário preencheu o TextBox com o Login - String.IsNullOrEmpty(txtLogin.Text)
  2. Verificamos se o valor informado possui tamanho menor que 5 - txtLogin.Text.Length < 5
  3. Se as condições acima forem atendidas então exibimos uma mensagem de ao usuário : MessageBox.Show("Informe um Login válido !", "Login", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
  4. Colocamos o foco no controle : txtLogin.Focus()
  5. E saímos da rotina que trata o evento Click : Return

Repetimos o procedimento acima para a senha.

Se o cliente informar um login e senha válidos deveremos realizar a verificação e validação das credenciais comparando-as com os valores existentes na tabela Clientes do banco de dados CiaFilmes.mdf.

Abaixo temos o código completo que implementa a verificação das credenciais informadas com as existentes no banco de dados:

 Private Sub btnSubmeter_Click(sender As Object, e As EventArgs) Handles btnSubmeter.Click
        'verifica se o usuário informou o login e senha válidos
        If String.IsNullOrEmpty(txtLogin.Text) Or txtLogin.Text.Length < 5 Then
            MessageBox.Show("Informe um Login válido !", "Login", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtLogin.Focus()
            Return
        End If
        If String.IsNullOrEmpty(txtSenha.Text) Or txtSenha.Text.Length < 5 Then
            MessageBox.Show("Informe uma senha válida !", "Senha", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtSenha.Focus()
            Return
        End If
        'define os objetos para realizar o acesso a tabela Clientes e verificar as credenciais
        'define os objetos command, connection e datareader

        Dim cmd As New SqlCommand
        Dim sqlCon As New SqlConnection
        sqlCon.ConnectionString = strConexaoSQLServer
        cmd.Connection = sqlCon
        cmd.CommandType = CommandType.Text
        cmd.CommandText = "SELECT * FROM Clientes WHERE login=@login AND senha=@senha"
        cmd.Parameters.AddWithValue("@login", txtLogin.Text)
        cmd.Parameters.AddWithValue("@senha", txtSenha.Text)
        Try
            'abre a conexao
            sqlCon.Open()
            ' Le a informação do banco de dados
            Dim dr As SqlDataReader = cmd.ExecuteReader
            'verifica se existem registros com as credenciais informadas
            If dr.Read Then
                Geral.clienteLogin = dr.Item("login")
                Geral.clienteCodigo = dr.Item("ClienteId")
                MessageBox.Show("Acesso permitido ! Bem Vindo """ & dr.Item("login") & """", "Login", MessageBoxButtons.OK,
MessageBoxIcon.Information)
                'esconde o formulário atual
                'Me.Hide()

                My.Forms.frmPesquisas.ShowDialog()
            Else
                'decrementa o numero de tentativas
                tentativas -= 1
                'se zerou as tentativas então encerra
                If tentativas = 0 Then
                    MessageBox.Show("Número de tentativas foi excedido. A aplicação será encerrada !", "Login", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                    'Fecha aplicação
                    Application.Exit()
                Else
                    'limpa as caixas de texto
                    txtLogin.Clear()
                    txtSenha.Clear()
                    MessageBox.Show("Login e/ou senha inválida ! Você tem mais " & tentativas.ToString & " tentativa(s).", "Login", MessageBoxButtons.OK, MessageBoxIcon.Error)
                End If
            End If
            'retorna o foco ao login
            txtLogin.Focus()
        Catch ex As Exception
            MessageBox.Show("Erro ao acessar os dados : " + ex.Message(), "Login", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        Finally
            sqlCon.Close()
        End Try
    End Sub

Abaixo temos um resumo da lógica do código:

Se as credenciais estiverem corretas o formulário de pesquisa será aberto, caso contrário o usuário possui 3 chances para informar um novo login e senha. Após isso a aplicação será encerrada.

Observe que estamos atribuindo valores às variáveis públicas clienteLogin e clienteCodigo definidas no módulo Geral. Assim poderemos consultar os valores dessas variáveis em quaisquer formulários.

O acesso a dados usando ADO .NET pode ser feita de diversas formas mas a sequência básica é quase sempre a mesma:

  1. Obter a string de conexão
  2. Abrir a conexão
  3. Definir um objeto Command
  4. Executar um comando SQL contra o banco dados
  5. Tratar os dados retornados como datareader ou dataset

As referência abaixo possuem artigos com mais detalhes sobre ADO .NET e seus recursos.

Na próxima aula continuaremos a definir o código do formulário desta vez do formulário Pesquisas : frmPesquisas.

Referências:


José Carlos Macoratti