Desenvolvendo Aplicativos Móveis com Windows Mobile Utilizando Microsoft Visual Studio 2008. Autor: Paulo Vinícius Moreira Dutra Versão: Beta 1 - Introdução O Visual Studio (VS) é um poderoso ambiente de desenvolvimento de aplicativos, sendo possível desenvolver aplicativos WEB, Windows e aplicativos para dispositivos móveis como pocket pc e smarth phone para Windows Mobile. Com VS é possível desenvolver em várias linguagens tais como, VB.NET( antigo visual basic ), C++ e C#. O VS C# será a linguagem utilizada para nossos exemplos da apostila, é uma linguagem poderosa orientada para componentes e objetos, sua sintaxe é semelhante às linguagens C, C++ e Java. 2 – Conhecendo o ambiente VS Ao inicializar o VS, a tela inicial é mostrada conforme a figura 2.1 abaixo. Figura 2.1 Projetos recentes Server Explorer - Conexões com base dados Solution Explorer – Exibe as classes, arquivos dos projetos utilizados Class View - Classes criadas e utilizadas pelo seu projeto 3 – Criando um novo projeto Figura 2.2 Na barra de ferramentas inicial clique em no botão para criar um novo projeto. Após pressionar o botão, a seguinte tela é exibida para definir qual linguagem e o tipo de projeto a ser criado. Escolha a Visual C#->Smart Device conforme mostrado à figura 2.3 abaixo. A versão do Framework .NET que será usado para desenvolver o projeto Figura 2.3 Project types: Tipos de projetos que podem ser criados. Templates: Template com configurações padrões para o novo tipo de projeto. Name: Nome do projeto. Location: Caminho do projeto. Solution: Define se um novo projeto será criado ou se será adicionado a um existente. Solution name: Nome do grupo de projetos. Na tela seguinte são definidas as configurações para o projeto móbile. Figura 2.4 TargetPlatform: O tipo de plataforma que o aplicativo será desenvolvido, Smarth Phone, Pocket PC entre outros. .NET Compact Framework version: Versão do framework .NET a ser usada para dispositivo móvel. O Compact Framework é uma versão reduzida do framework .NET. Device Application: Template padrão para a aplicação. Class Library: Template para biblioteca de classes. Console Application: Projeto em modo console sem interface gráfica. Control Library: Cria um componente customizado. Empty Project: Cria um projeto vazio sem nenhuma configuração. IMPORTANTE: Existem diferenças ao devolver aplicações para SmartPhone e Pocket PC, sendo que alguns recursos não podem estar disponíveis na aplicação, como por exemplo nas aplicações Smartphone não é possível adicionar um botão no formulário, somente nas aplicações Pocket PC. ToolBox- Componentes que podem ser usados para desenvolver a interface do aplicativo. Form Design – Representa a interface do sistema e onde serão adicionados os componentes. Figura 2.5 OutPut – Exibe mensagens de inicialização da aplicação, erros, e depuração Properties – Exibe as propriedades e eventos dos componentes selecionados no formulário. 2.1 - Conhecendo a barra de ferramentas - Executa a aplicação em modo Debug ou Realease: O modo Debug deve ser usado quando se esta desenvolvendo a aplicação é fazendo testes, já o Release é usado quando a aplicação está pronta como produto final. - Permite ter acesso rápido ao Solution Explorer, janela de Propriedades é ToolBox. - Nesta barra é possível configurador qual emulador será usado para testar as aplicações, ou se aplicação será executada direto no dispositivo smarth phone ou pocket PC. O toolbox contém diversos componentes úteis para desenvolvimento da interface, tais como botões e rótulos. Figura 2.1.1. IMPORTANTE: Existem diferenças ao devolver aplicações para SmartPhone e Pocket PC, sendo que alguns recursos não podem estar disponíveis na aplicação, como por exemplo nas aplicações Smartphone não é possível adicionar um botão no formulário, somente nas aplicações Pocket PC. Continuando, adicione dois componentes TextBox, dois Labels é um botão, conforme mostrado a figura 2.1.2 abaixo. Figura 2.1.1 Figura 2.1.2 Com os componentes adicionados no formulário é necessário alterar a propriedade name dos componentes e dos rótulos. Altere as seguintes propriedades dos componentes: label1 Name: lblNome Text: Nome label2 Name: lblSobreNome Text: Sobre Nome Para os TextBox altera somente a propriedade Name: textBox1 Name: txtNome textBox2 Name: txtSobreNome button1 Name: btnOk Text: Ok Figura 2.1.3 Propriedades comuns dos componentes. BackColor: Define a cor de fundo dos componentes ForeColor: Define a cor do texto do componente TextAlign: Permite alinhar o texto a direita, centro ou esquerda Font: Configura a fonte do componente Enabled: Define se o componente estará habilitado ou não Visible: Define se o componente é visível ou não Locked: Permite bloquear a movimentação do componente na tela em tempo de design, muito útil quando a interface esta pronta, evitando que movamos os componentes sem intenção. DataBindings: Permite vincular o componente a uma fonte de dados, como por exemplo um determinado campo de uma tabela da base de dados. As propriedades descritas acima são comuns a maioria dos componentes, dependendo do tipo de componente utilizado algumas propriedades serão diferentes, como por exemplo, em um botão não existe a propriedade TextAlign. 2.2 – Implementando o código Antes de implementar o código é necessário entender como VS separa o código na aplicação. Acesse o Solution Explorer e expanda a árvore do projeto conforme mostrado na figura 2.2.1. Quando criamos o nosso projeto o VS criou três classes (Form1.cs, Form1.Designer.cs e Program.cs) e um arquivo de recurso (Form1.resx). A classe Program.cs é a principal da aplicação, pois é ela que contém o método Main() pra iniciar o aplicativo. Ver figura 2.2.4. A classe Form1.Designer.cs contém todo o código para montar o layout do formulário com os componentes. A classe Form1.cs é onde será implementado toda lógica da aplicação. Ambas as classes Form1.Designer.cs e Form1.cs são como se fossem uma única classe. A palavra reservada partial, indica que a classe está divida em partes diferentes. Veja as figuras 2.2.2 e 2.2.3 Figura 2.2.1 A palavra reserva namespace é usada quando queremos agrupar as classes do projeto é muito útil quando temos várias classes no projeto e queremos agrupar as de acordo com sua funcionalidade. Figura 2.2.2 – Classe Form1.cs Figura 2.2.3 – Classe Form1.cs Figura 2.2.4 – Classe Program.cs Depois que entendemos um pouco sobre a estrutura do projeto agora podemos implementar um pequeno trecho de código. De um duplo clique sobre o botão btnOk. O seguinte código da figura 2.1.5 é gerado automaticamente quando efetuamos um duplo click no componente de botão, o evento gerado é do tipo Click, ou seja, quando o botão recebe um click do mouse, existem diversos tipos de eventos, basta acessar a janela de propriedades e clicar no ícone de eventos . Figura 2.1.5 – Código gerado automaticamente para o evento do botão Janela de propriedades exibindo eventos do botão. O método gerado é vinculado ao evento do botão Figura 2.1.6 – Janela de eventos do botão Implemente o seguinte trecho de código no evento do botão. //Exibe uma mensagem simples MessageBox.Show("Seja bem-vindo: " + txtNome.Text + " " + txtSobreNome.Text, "Mensagem"); O código exibe uma mensagem simples, com as informações dos componentes TextBoxs. A classe MessageBox é utilizada para exibir caixas de diálogos com informações para os usuários. Agora é necessário compilar a aplicação, acesse o menu Build e clique em “Build HelloWord”, veja que o menu informa o nome do projeto que vai ser compilado. Figura 2.1.7 – Menu Build Janela de saída informando que o projeto foi compilado com sucesso. Este processo é necessário se quisermos verificar se aplicação contém algum erro antes de executá-la. Figura 2.1.8 – Janela de Saída Para executar a aplicação clique no botão “Start Debugging”, será exibida à seguinte janela da figura 2.1.9, para selecionar qual tipo de dispositivo a aplicação deverá ser executa, deixa a opção padrão selecionada e clique no botão Deploy. Figura 2.1.9 – Janela de Deploy da aplicação 3 - Caixas de diálogo Vimos no exemplo anterior um pequeno exemplo inicial utilizando caixas de diálogos, que são muito importantes quando queremos exibir mensagens para usuário, tais como, de informação, avisos é entre outras. Crie um novo projeto clicando no botão New Project da barra de ferramentas, após exibir a caixa de diálogo escolha a opção Visual C#->Smart Device. Altere o nome do projeto para CaixasDeDialogo. Adicione os botões no formulário conforme mostrado a figura 3.1. 1 4 2 5 3 6 7 Figura 3.1 – Formulário Vamos alterar agora as propriedades dos botões: 1 - Name: btnMsgSimples: 2 - Name: btnMsnComRotulo: Text: Mensagem Simples Text: Mensagem Simples com rótulo 3 - Name: btnMsgInformativa1: Text: Mensagem de informação tipo 1 4 - Name: btnMsgInformativa2: Text: Mensagem de informação tipo 2 5 - Name: btnMsgPergunta: Text: Mensagem de pergunta 6 - Name: btnMsgErro: Text: Mensagem de erro 7 - Name: btnMsgSemIcone: Text: Mensagem sem simbolo Para exibir as mensagens utilizamos a classe MessageBox que possui um método sobrecarregado chamado Show que é responsável por exibir as mensagens do sistema. Métodos da classe MessageBox Permite exibir uma caixa de diálogo Show(String text) simples. Permite exiber uma caixa de diálogo Show(String text, String caption) espeficiando a mensagem é o título. Permite exibir uma caixa de diálogo Show(String, text String caption, espeficando a mensagem, o título, os MessageBoxButtons button, botões, ícone e qual o botão default que MessageBoxIcon icon, irá aparecer selecionado MessageBoxDefaultButton defaultButton) A constante MessageBoxButtons define quais tipos de botões deverão aparecer na caixa de diálogo, os possíves valores da constante é mostrado na tabela abaixo. Constante MessageBoxButtons A caixa de diálogo contém apenas o OK botão OK A caixa de diálogo contém os botões Ok OKCancel e Cancel A caixa de diálogo contém os botões AbortRetryIgnore Abort, Retry e Ignore A caixa de diálogo contém os botões YesNoCancel Yes, No e Cancel A caixa de diálogo contém os botões YesNo Yes e No A caixa de diálogo contém os botões RetryCancel Retry e Cancel A constante MessageBoxDefaultButton que define qual será o botão default do da caixa de diálogo. Constante MessageBoxDefaultButton Define que o primeiro botão será o botão Button1 default Define que o segundo botão será o botão Button2 default Define que o terceiro botão será o botão Button3 default Para implementar o código nos botões basta dar um duplo click no botão desejado. Observe que ao clicarmos em qualquer um dos botões o código para a execução do evento de Click é automaticamente gerado, bastando apenas implementar os códigos necessários. Figura 3.2 – Código do evento de Click gerado. Segue abaixo o código de eventos de Click de cada botão. Código para o botão: btnMsgSimples private void btnMsgSimples_Click(object sender, EventArgs e) { MessageBox.Show("Mensagem simples"); } Código para o botão: btnMsnComRotulo private void btnMsgComRotulo_Click(object sender, EventArgs e) { MessageBox.Show("Mensagem simples com rótulo", "Mensagem"); } Código para o botão: btnMsnInformativa1 private void btnMsgInformativa1_Click(object sender, EventArgs e) { MessageBox.Show("Mensagem informativa", "Informativa", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); } Código para o botão: btnMsnInformativa2 private void btnMsgInformativa2_Click(object sender, EventArgs e) { MessageBox.Show("Mensagem informativa", "Informativa", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1); } Código para o botão: btnMsgPergunta private void btnMsgPergunta_Click(object sender, EventArgs e) { if (MessageBox.Show("Mensagem informativa", "Informativa", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes) { essageBox.Show("Você clicou no botão sim"); } else { MessageBox.Show("Você clicou no botão não"); } } Código para o botão: btnMsgErro private void btnMsgErro_Click(object sender, EventArgs e) { MessageBox.Show("Mensagem de erro", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } Código para o botão: btnMsgSemIcone private void btnMsgSemIcone_Click(object sender, EventArgs e) { MessageBox.Show("Mensagem sem simbolo", "Sem simbolo", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1); } 4 – Trabalhando com banco de dados Para realizar conexões de banco de dados utilizando o .Net Compact Framework é utilizado tecnologia ADO.NET que é a evolução do ActiveX Data Object (ADO), muito utilizado para desenvolvimento de aplicativos desktop e web. A nova tecnologia ADO.NET contém várias melhorias em relação a sua arquitetura, fornecendo um melhor desempenho. Os principais componentes utilizados pelo ADO.NET na versão móbile são DataSet e DataTable que se encontra no namespaces System.Data , os componentes SqlCeCommand, SqlCeConnection, SqlCeDataAdapter e SqlCeDataReader ambas se encontram no namespaces System.Data.SqlServerCe. O componente DataSet mantém os dados recuperados do banco dados em cachê de memória já o componente DataTable representa a tabela do banco de dados. Para entendermos melhor como trabalhar com banco dados utilizando Windows Mobile vamos implementar um simples cadastro de CDs. Na versão mobile para armazenamento de dados existe uma versão compacta do SQL Server, conhecida como SQL Server Compact, ou seja, é um banco de dados com funcionalidades mais simples, somente para comportar dados nos dispositivos móveis que utilizam Windows Mobile. Inicialmente o sistema de cadastro terá apenas as seguintes funcionalidades • • • Cadastro de Autores; Cadastro de CDs; Menu para acesso aos cadastros; 4.1 – Iniciando o projeto de Cadastro de CDs Siga os passos do tópico “3 – Criando um novo projeto” para criamos o projeto de CDs, apenas defina o nome do projeto como Cadastro de CDs Figura 4.1 – Definindo o nome do projeto 4.2 – Criando um menu principal A formulário do menu principal é bem simples, quando é iniciado um novo projeto automaticamente é adicionado um componente de menu no formulário e também cada novo formulário adicionado o componente também é criado. Figura 4.2 – Formulário Componente de menu criado automaticamente A edição dos menus é bem simples, basta apenas selecionar o componente de menu ou efetuar um duplo clique na parte inferior do formulário. Quando iniciamos a edição do menu é exibido a descrição Type Here (Digite aqui). De um duplo clique aqui para iniciar a edição do menu. Figura 4.3 – Menu Agora vamos dar ínicio a edição dos menus. Defina a descrição dos menus conforme a figura abaixo. Veja também na figura há várias descrições Type Here,assim é possivel adicionar novos menus e submenus. 4 1 2 3 5 Figura 4.3 – Menus Vamos alterar agora as propriedades dos menus, acesse o menu properties. 1 - Name: mnuAutores Text:Autores 3 - Name: mnuCDs Text: CDs 3 - Name: mnuCadastros Text: Cadastro 4 - Name: mnuSair Text: Sair 5 - Name: mnuPrincipal Figura 4.3 – Janela de Propriedades Selecione o formulário principal é altere as seguintes propriedades: Name: frmPrincipal Text: Principal 4.3 – Criando uma base de dados Com o layout do formulário principal criado, agora vamos criar a base de dados do sistema. Acesse o menu Data->Add New DataSource conforme a figura 4.4. Figura 4.4 – Acessando menu Data Na janela seguinte devemos definir qual será a fonte de dados. São definida três opções DataBase: Dados vindos de uma base de dados como o SQL Server Compact. Web Service: Dados vindos de um web service, na qual devemos fornecer uma URL. Object: Define que a fonte será fornecida através de um objeto Selecione a opção DataBase e clique no botão Next. Figura 4.5 – Definindo a cor da nossa fonte de dados Na janela seguinte “Choose Your Data Connection” é onde devemos criar uma nova conexão com a base dados ou usar alguma já existente. Caminho onde se encontra a base de dados Permite criar uma nova conexão Figura 4.6 – Criando ou definindo uma nova conexão String de conexão utilizada pelo ADO.NET para conectat a base de dados Clique no botão New Connection para criamos uma nova conexão. Na janela Add Connection devemos definir as propriedades de conexões: As opções que aparecem quando adicionamos uma nova conexão pertencem a versão full SQL Server, devemos alterar para a versão do SQL Server Compact. Clique no botão Change para alterar o fornecedor de fonte de dados, e selecione Microsof SQL Server Compact 3.5 e clique em Ok. Figura 4.8. Figura 4.7 – Adicionando uma nova conexão Figura 4.8 – Selecionando o DataSource Veja que as opções de conexão foram alteradas para a versão do Microsoft SQL Server Compact. DataSource: Define onde deve ficar armazena minha a fonte de dados Connection Properties: Define o nome da base de dados e a senha de acesso Clique no botão Create para criamos as configurações da nossa base de dados. Figura 4.8 – Adicionando uma nova conexão Caminho onde deve ser criado a base de dados. Defina o caminho onde o projeto foi criado. Também é possível definir o nome da base de dados Define como deve ser classificado seu banco de dados. Sempre utilize a configuração do país que esta utilizando a base. Figura 4.9 – Configurações da base de dados Depois de prontas as configurações, defina a senha como aula e clique em OK. Será exibida uma mensagem informando que a senha é muito curta e fraca, clique YES para confirmar que você quer usar a senha assim mesmo. Na janela Add Connection clique no botão Test Connection para testar a conexão, depois clique em OK. Após configurar a base de dados, selecione a opção Yes, include sensitive data in connection string. Clique em Next. Na janela seguinte é onde será definido o nome do DataSet, clique em Finish. Figura 4.10 – Criando ou definindo uma nova conexão Figura 4.11 – Definindo o nome do DataSet No Solution Explorer foram criados o arquivo da base de dados (DADOS.sdf) o DataSet (DADOSDataSet), lembrando que o DataSet mantém os dados recuperados do banco dados em cachê de memória. E no DataSet que iremos adicionar os objetos de tabela DataTable Agora para o próximo passo será necessário criar as tabelas da base de dados, para isso clique na guia Server Explorer. Figura 4.12– DataSet e Banco criados Expanda a árvore é clique com botão direito no item Table e acesse o menu Create Table, para criamos as tabelas. Figura 4.13– Criando as tabelas Neste momento é onde devemos criar os campos e definir o nome da tabela, sendo uma tarefa bem simples, veja a figura 4.14. TABELA: AUTORES Column Name DataType Length CODAUTORES numeric NOME nvarchar 5 50 TABELA: CD Column Name DataType Length CODCOD CODAUTORES DESCRICAO TIPO numeric numeric nvarchar nvarchar 5 5 50 10 TABELA: DADOSCD Column DataType Name CODCOD numeric CODCD numeric DESCRICAO nvarchar TIPO nvarchar Length 5 5 50 10 Allow Nulls No Yes Unique PrimaryKey Yes No Yes No Allow Nulls No Yes Yes Yes Unique PrimaryKey Yes No No No Yes No No No Unique PrimaryKey Yes No No No Yes No No No Allow Nulls No Yes Yes Yes Figura 4.14 – Criando uma nova tabela 4.4 – Criando objetos DataTable O objeto DataTable representa uma ou mais tabelas de dados em memória. Os objetos DataTable estão contidos no objeto DataSet. Veja abaixo as principais propriedades é métodos do objeto DataTable: Propriedades: • Columns – Retorna as colunas da tabela através de uma coleção de objetos DataColumn (DataColumnCollection); • Rows – Retorna as linhas da tabela através de uma coleção de objetos DataRow (DataRowCollection); • PrimaryKey – retornas colunas de chave primária através de um array de objetos DataColumn; • TableName – Define ou retorna do objeto DataTable. Métodos • AcceptChanges - Efetiva as alterações realizadas no DataTable no banco de dados. • NewRow - gera um novo objeto DataRow que representa uma linha de dados. • Copy - copia os dados e a estrutura do DataTable. • Clear - limpa os dados de um DataTable. • RejectChanges - ignora as alterações feitas no DataTable. Agora que podemos iniciar a criação dos objetos DataTable, selecione a guia Solution Explorer ou pressione Ctrl+Alt+L. De um duplo clique no item DADOSDataSet.xsd para visualizar o editor de Designer, é neste momento que iremos criar os objeto DataTable. Após visualizar o designer selecione a guia Server Explorer ou pressione Ctrl+Alt+L. Figura 4.15 – Solution Explorer Por fim, selecione, por exemplo, a tabela AUTORES e arraste com o mouse para dentro do designer, faça a mesma coisa com a tabela CD e DADOSCD, devendo ficar conforme a figura 4.16. Figura 4.16 – Editor de Designer dos relacionamentos. Ao adicionarmos um componente DataTable no designer é gerado varias classes, como por exemplo, para a tabela AUTORES são geradas as classes : AUTORESDataTable herdando da classe DataTable, AUTORESRow herdando a classe DataRow, e AUTORESTableAdapter que contém as regras para conexão, preenchimento da tabela atualizações com a base de dados. A classe DataRow representa a linha do componente DataTable ou um registro da tabela do banco de dados Veja abaixo as principais propriedades é métodos do objeto DataRow: Propriedades: • RowState – Retorna o estado da linha da tabela especifica pela constante DataRowState; • TableName – retorna o nome do objeto DataTable relacionado com a linha. Métodos • AcceptChanges - Efetiva as alterações realizadas no DataRow; • BeginEdit – inicia a edição da linha; • CancelEdit – cancela a edição da linha; • Delete – exclui a linha atual do objeto DataTable. IMPORTANTE: Quando criamos as instâncias dos objetos DataTable foram criados também classes que herdam de DataRow, uma para cada objeto DataTable, por exemplo para a tabela AUTORES foi criado uma classe chamada AUTORESRow, e para tabela CD foi criado a classe CDRow e por fim para a tabela DADOSCD foi criado a classe DADOSCDRow. cada classe filha de DataRow contém uma instância de DataColumn representando cada coluna da tabela. E Como próximo passo será necessário definir os relacionamentos entre as tabelas, lembrando que, o relacionamento esta entre a tabela AUTORES -> CD, E CD -> DADOSCD. As definições dos relacionamentos podem ser feitas selecionando o campo da chave primária da tabela de origem (Parent Table), com o botão esquerdo do mouse pressionado arraste-o até a tabela de destino (Child Table), com isso a janela de configuração dos relacionamentos deve aparecer conforme a figura 4.17. Na figura 4.17 o relacionamento foi realizado entre a tabela AUTORES e CD. Veja que na listagem Columns são listados os campos de cada tabela Parent Table e ChildTable. Na listagem Parent Table selecione o campo da chave primária da tabela, na listagem Child Table selecione o campo que se refere ao campo da chave estrangeira, conforme mostrado a figura 4.17. Figura 4.17 – Definindo o Relacionamento Selecione também a opção Foreign Key Constraint Only. Veja abaixo a descrições das opções de relacionamento: Both Relation and Foreign Key Constraint Cria um relacionamento e restrição de uma chave estrangeira (Ver as descrições abaixo). Foreign Key Constraint Only Restringe ação a ser executada quando um valor em uma coluna (ou colunas) é excluído ou alterado. Relation Only A classe DataRelation é usada pata relacionar dois objetos DataTable através de DataColumn. Update rule Especifica as regras de alterações para os registros filhos (Child Table) quando o registro pai (Parent Table) é atualizado. Delete rule Especifica as regras de alterações para os registros filhos (Child Table) quando o registro pai (Parent Table) é excluído. Accept/Reject rule Especifica as regras de alterações para os registros filhos (Child Table) quando houver alterações ou cancelamento no registro pai (Parent Table). Figura 4.18 – Relacionamento entre os componentes DataTable definidos. Para finalizar a configuração dos objetos DataTable será necessário definir cada os campos de chave primária como auto-incremento. Por exemplo, clique no campo CODAUTORES do componente DataTable AUTORES conforma a figura 4.19. Acesse a janela de propriedades é altere a propriedade do campo AutoIncrement para True e AutoIncrementSeed e AutoIncrementStep para 1. Repita o mesmo procedimento para os outros objetos DataTable. Figura 4.19 – Alterando as propriedades do campo. 5 – Desenvolvendo os formulários de cadastros Criar os formulário de cadastro é bem simples basta apenas arrastar os componentes no ToolBox para dentro do formulário. Para criar os formulários de cadastro é necessário adicionar novos formulários, basta apenas clicar com o botão direito do mouse sobre o nome do projeto no Solution Explorer, selecionar menu Add->New Item conforme mostrado a figura 5.1. Na janela seguinte figura 5.2 selecione a categoria Windows Forms e no Template também selecione o item Windows Forms e defina o nome do formulário como FrmCadAutores como mostrado a figura abaixo, veja que é colocado a extenção .cs indicando que um arquivo de código fonte do C#. Figura 5.1 – Adicionando novo formulário Figura 5.2 – Adicionando um novo formulário Windows Forms Depois de adicionado o formulário, agora podemos adicionar os componentes necessários. Defina o layout conforme mostrado nas figuras 5.3 e 5.4. Primeiramente será necessário adicionar o componente TabControl para criar as guias. Para alterar as propriedades Name e Text de cada guia clique na área interna do componente. 1 2 3 6 4 7 5 9 8 10 12 11 Figura 5.3 – Layout guia de Dados do formulário cadastro de autores Altere as propriedades dos componentes conforme a descrição abaixo: Item Componente Propriedade Name Propriedade Propriedade Text Enabled Label lblCodigo Código 1 TextBox txtCodigo False 2 Label lblNome Nome 3 TextBox txtNome 4 Button btnNovo Novo True 5 Button btnExcluir Excluir False 6 Button btnCancelar Cancelar False 7 TabControl tabDados 8 Para alterar as propriedades das guias clique no interior delas TabPage tabPagDados Dados 9 TabPage tabPagConsulta Consulta 10 MenuItem mnuVoltar Voltar 11 MenuItem mnuSalvar False 12 1 4 2 3 5 Item 1 2 3 4 5 Figura 5.4 – Layout guia de Consulta do formulário cadastro de autores Componente Propriedade Name Propriedade Text Label lblCampo Campo ComboBox cbCampo TextBox txtPesquisa Button btnPesquisar ... DataGrid grdDados Selecione o componente ComboBox e acesse a janela Properties do componente, localize a propriedade Itens e adicione os valores conforme mostrado a figura Figura 5.5 – Itens ComboBox A vinculação é realiza através da propriedade DataBindings dos componentes. Primeiro vamos realizar a vinculação com o objeto txtCodigo(TextBox). Selecione o componente TextBox ( txtCodigo ) que esta na guia dados, acesse a propriedade DataBindings clique na listagem Text, para exibir as possíveis fontes de dados existentes para vinculação, selecione a tabela AUTORES e por fim o campo NOME. Conforme mostrado a figura ao lado. Objeto txtCodigo. Figura 5.6 – Vinculando componentes ao objeto DataTable Seguindo o procedimento descrito anteriormente estamos vinculando ao campo do objeto DataTable. Ao criamos a primeira vinculação automaticamente é criado três componentes na barra inferior, que são respectivamente a instância da classe DADOSDataSet, instância do componente BindingSource que vincula a propriedade do componente ao campo do objeto DataTable e por último instância de TableAdapter que é utilizado para buscar é salvar e excluir os dados na base de dados. Para vincular o objeto txtNome (TextBox) ao campo NOME do objeto DataTable, basta acessar a propriedade do DataBindings e selecionar a listagem Text, não será mais necessário selecionar o item Other Data Source depois que realizamos o primeiro binding, basta apenas selecionar o componente aUTORESBindingSource, pois neste já esta contido a vinculação com o objeto DataTable, veja a figura ao lado. E por fim selecione o componente DataGrid que esta na guia Consulta e selecione a propriedade DataBindings em seguida selecione DataSource para definir a fonte de dados que será usado para exibir os dados da tabela AUTORES veja a figura abaixo. Devemos agora alterar a propriedade name dos componentes de dados para tornar a digitação do código mais simples. 1 Item 1 2 3 2 Componente DataSet BindingSource TableAdapter Propriedade Name dsDados bsAutores taAutores 3 Propriedade Text 5 – Implementando código do cadastro de Autores Depois de configurar o layout do cadastro de autores agora podemos implementar os códigos necessários para o seu funcionamento. Acesse o formulário de cadastro FrmCadAutores no Solution Explorer, caso esteja em modo de designer pressione F7 para exibir o editor de códigos, ou clique com botão direito sobre o nome do formulário no Solution Explorer é selecione o menu View Code. Devemos primeiramente implementar os objetos que iremos usar. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - using using using using using using using using using System; System.Linq; System.Collections.Generic; System.ComponentModel; System.Data; System.Data.SqlServerCe; System.Drawing; System.Text; System.Windows.Forms; - namespace Cadastro_de_CDS - { public partial class FrmCadAutores : Form { //Objeto que representa a linha do objeto DataTable private DADOSDataSet.AUTORESRow row; 16 17 //Objeto de conexão com a base de dados 18 private SqlCeConnection conexao; 19 20 //String de conexão com a base de dados 21 private const String STRCONN = @"Data Source=\Program Files\Cadastro_de_CDS\Dados.sdf;Password=aula;Persist Security Info=True"; 22 public FrmCadAutores(){ 23 InitializeComponent(); 24 } As linhas de 1 a 9 são as importações do namespaces que pertencem ao .NET, que contém as classes padrões utilizadas pelo projeto como por exemplo o TextBox e Label. A linha 10 identifica em qual namespace ou pacote se encontra o projeto, já na linha 12 temos a declaração da classe FrmCadAutores que é o formulário de cadastro de autores. As linhas de 1 a 13 e de 22 a 24 são geradas automaticamentes pelo Visual Studio então não é necessário implementa-las, apenas as linhas 14 a 21. A linha 15 criamos a váriavel da classe AUTORESRow que representa a linha do registro do objeto DataTable. A classe AUTORESRow foi gerada automaticamente quando criamos os DataTable no tópico 4.4 – Criando objetos DataTable. Veja que é necessário chamar a classe DADOSDataSet pois o objeto DataTable AUTORES pertence a este DataSet. Para cada objeto DataTable foi criado uma classe que extende o objeto DataRow, ver tópico 4.4 – Criando objetos DataTable, para mais detalhes. A linha 18 representa o objeto de conexão, a classe SqlCeConnection é responsável por abrir e fechar as conexões com a base de dados. Na linha 21 temos a uma constante do tipo String que contém os dados necessários para se conectar a base de dados, veja que na String o valor “Data Source” aponta para caminho do aplicativo instalado no Windows Mobile. private const String STRCONN = @"Data Source=\Program Files\Cadastro_de_CDS\Dados.sdf;Password=aula;Persist Security Info=True"; O código abaixo foi implementado no evento Load do formulário executado sempre que o é carregado. Para implementar o código no evento Load, pressione F7 se estiver na edição de código para visualizar o modo de designer ou selecione o arquivo FrmCadAutores no Solution Explorer, depois clique com o botão direito é selecione o menu View Designer. Na janela de propriedades clique no icone para exibir os eventos e de um duplo clique no evento Load. Implemente o código descrito abaixo. 5.1 - Código para o evento Load do formulário try { //Criando instância do objeto SqlCeConnection conexao = new SqlCeConnection(); //Definindo a string de conexão conexao.ConnectionString = STRCONN; //Abre uma conexão com a base de dados conexao.Open(); //Seta o objeto SqlCeConnection da propriedade do objeto //TableAdapter this.taAutores.Connection = conexao; //Prenche o objeto DataTable com os dados da base de dados this.taAutores.Fill(this.dsDados.AUTORES); if (dsDados.AUTORES.Rows.Count > 0) btnExcluir.Enabled = true; else btnExcluir.Enabled = false; //Selecionando o indíce padrão do ComboBox cbCampo.SelectedIndex = 0; } catch (SqlCeException ex) { MessageBox.Show("Não foi possível conectar a base de dados. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } O código para conexão foi colocado dentro de um bloco try…catch para tratar os possíveis erros de conexão, como por exemplo quando o aplicativo não consegue se conectar a base de dados. Veja também que o tipo de erro a ser tratado é do tipo SqlCeException, que retorna todos os avisos é erros emitidos pelo Microsoft SQL Server 2005 Compact Edtion. try { //Implementação de código catch (SqlCeException ex) { MessageBox.Show("Não foi possível conectar a base de dados. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } As três primeiras linhas contidas dentro do bloco try...catch, estamos criando a instância do objeto connection, na linha seguinte é passado a constante que contém a string de conexão com a base de dados e por último estamos abrindo a conexão com o método Open() da classe. Isso é o básico que precisamos para conectar com o banco de dados. //Criando instância do objeto SqlCeConnection conexao = new SqlCeConnection(); //Definindo a string de conexão conexao.ConnectionString = STRCONN; //Abre uma conexão com a base de dados conexao.Open(); É por fim definimos a instância do objeto SqlCeConnection na propriedade Connection do componente TableAdaper. O método Fill do objeto TableAdapter é usado para preencher o componente DataTable com os dados da base de dados, internamente o método executa um código SQL para trazer esses dados. //Seta o objeto SqlCeConnection da propriedade do objeto //TableAdapter this.taAutores.Connection = conexao; //Prenche o objeto DataTable com os dados da base de dados this.taAutores.Fill(this.dsDados.AUTORES); Método TrataBotoes: private void TrataBotoes(String state) { if ( (state.Equals("novo")) || (state.Equals("editar"))){ btnNovo.Enabled = false; btnCancelar.Enabled = true; btnExcluir.Enabled = false; mnuSalvar.Enabled = true; } else if ((state.Equals("salvar")) || (state.Equals("cancelar"))) { btnNovo.Enabled = true; btnCancelar.Enabled = false; mnuSalvar.Enabled = false; } if ( (state.Equals("salvar")) || ( state.Equals("cancelar") ) || (state.Equals("excluir")) ) { if (dsDados.AUTORES.Rows.Count > 0) { btnExcluir.Enabled = true; } else btnExcluir.Enabled = false; } } O método TrataBotoes é responsável por tornar os botões habilitados ou desabilitados de acordo com a ação executado no cadastro. O método é auto-explicativo por isso não será detalhado. Agora vamos implementar o código para os botões Novo, Excluir, Cancelar e o menu Salvar. Para implementar o código, basta dar um duplo clique no botão para gerar o evento de Click. 5.2 - Código para o evento Click do botão Novo: btnNovo txtNome.Text = ""; txtCodigo.Text = ""; TrataBotoes("novo"); txtNome.Focus(); //Criando instância de um novo objeto DataRow row = dsDados.AUTORES.NewAUTORESRow(); O código para o botão Novo (btnNovo) é bem simples, nas duas primeiras linhas o conteúdo dos componentes TextBox e limpado, logo em seguida o método TrataBotoes é chamado para tornar os botões habilitados ou desabilitados. O método Focus() é chamado pelo objeto txtNome (TextBox) par definir o foco no componente. A linha descrita abaixo cria uma instância da classe AUTORESRow que representa a linha do objeto DataTable. //Criando instância de um novo objeto DataRow row = dsDados.AUTORES.NewAUTORESRow(); 5.3 - Código para o evento Click do botão Excluir: btnExcluir try { if (MessageBox.Show("Deseja realmente excluir o registro", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes) { //Exclui o autor taAutores.Delete(Int32.Parse(txtCodigo.Text)); //Comita todas as mudanças realizadas no objeto DataTable dsDados.AUTORES.AcceptChanges(); //Prenche o objeto DataTable com os dados da base de dados this.taAutores.Fill(this.dsDados.AUTORES); MessageBox.Show("Excluido com sucesso"); TrataBotoes("excluir"); } } catch (SqlCeException ex) { //Desfaz as alterações caso ocorra algum erro dsDados.AUTORES.RejectChanges(); MessageBox.Show("Não foi possível excluir o registro. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } Veja que o código inicial contido dentro do bloco try..catch, quando executado exibe uma mensagem de confirmação, perguntando se o usuário quer mesmo excluir o registro. Para mais detalhes sobre caixas de diálogo veja o tópico 3 - Caixas de diálogo. if (MessageBox.Show("Deseja realmente excluir o registro", "Aviso", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes) { //Implementação do código } Nas linhas seguintes o método Delete do objeto TableAdapter é chamado para excluir o registro que deve ser passado como parâmetro o código do registro ou seja o campo que corresponde a chave primária da tabela. O método AcceptChanges() pertence ao objeto DataTable, ele comita todos as alterações ou exclusões na base de dados. Lembrando que para acessar a instância do objeto DataTable é necessário primeiro chamar o objeto DataSet como mostrado no código abaixo. É por último é chamado o método Fill para atualizar o objeto DataTable com os dados da base de dados. //Exclui o autor taAutores.Delete(Int32.Parse(txtCodigo.Text)); //Comita todas as mudanças realizadas no objeto DataTable dsDados.AUTORES.AcceptChanges(); this.taAutores.Fill(this.dsDados.AUTORES); Lembrando também que o código esta contido dentro de um bloco try catch para tratar quaisquer exceções que possam ocorrer. Veja também que no bloco catch estamos chamando o método RejectChanges() que é utilizado para desfazer quais alterações que tenham sido realizados quando houver algum erro. try { //Implementação de código } catch (SqlCeException ex) { //Desfaz as alterações caso ocorra algum erro dsDados.AUTORES.RejectChanges(); MessageBox.Show("Não foi possível excluir o registro. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } 5.4 - Código para o evento Click do botão Cancelar: btnCancelar try { //Desfaz todas as alterações realizadas no DataTable dsDados.AUTORES.RejectChanges(); row = null; //Prenche o objeto DataTable com os dados da base de dados this.taAutores.Fill(this.dsDados.AUTORES); TrataBotoes("cancelar"); } catch (SqlCeException ex) { //Desfaz as alterações caso ocorra algum erro dsDados.AUTORES.RejectChanges(); MessageBox.Show("Erro ao cancelar o registro. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } O código para o botão cancelar também é bem simples. O método RejectChanges() do objeto DataTable é chamado para desfazer qualquer alterações, também e definido a instância do objeto DataRow como null é por ultimo o método Fill é chamado para atualizar o DataTable com os dados da base de dados. 5.5 - Código para o evento Click do menu Salvar: mnuSalvar try { if (txtNome.Text == "") { MessageBox.Show("Preencha o campo nome", "Campo em branco", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); txtNome.Focus(); } else { row.NOME = txtNome.Text; //Verificando se a linha foi criada if ((row.RowState == DataRowState.Detached)){ //Adicionando o objeto DataRow no objeto DataTable autores dsDados.AUTORES.AddAUTORESRow(row); } //Comitando os dados taAutores.Update(dsDados.AUTORES); //comita todas as mudanças realizadas no objeto DataTable dsDados.AUTORES.AcceptChanges(); TrataBotoes("salvar"); Continuação MessageBox.Show("Registro salvo com sucesso."); } } catch (SqlCeException ex) { //Desfaz as alterações caso ocorra algum erro dsDados.AUTORES.RejectChanges(); MessageBox.Show("Não foi possível conectar a base de dados. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } No método salvar está verificando se o campo Nome (txtNome) está em branco, se estiver exibe uma mensagem é transfere o foco para o componente para que seja preenchido. if (txtNome.Text == "") { MessageBox.Show("Preencha o campo nome", "Campo em branco", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); txtNome.Focus(); } else { ......... Caso tenha sido preenchido é executa as linhas descritas abaixo. O objeto row que é uma instância da classe AUTORESRow, chama a propriedade NOME que é uma coluna do DataTable, devemos atribuir o valor do TextBox correspondente ao campo nome nesta propriedade do objeto é adicionar no método AddAUTORESRow do objeto DataTable. Antes de ser adicionado no DataTable é verificado se a instância do objeto DataRow está Detached (destacado), ou seja, se ainda não foi salvo na base de dados. row.NOME = txtNome.Text; //Verificando se a linha foi criada if ((row.RowState == DataRowState.Detached)){ //Adicionando o objeto DataRow no objeto DataTable autores dsDados.AUTORES.AddAUTORESRow(row); } O método AddAUTORESRow foi criado no momento que criamos o objeto DataTable (ver tópico 4.4 – Criando objetos DataTable para mais detalhes), que espera em seu parâmetro a instância da classe AUTORESRow, para visualizar a implementação deste método, basta posicionar o cursor do mouse sobre o método é pressionar F12. Outra forma de adicionar seria chamando o método Add da propriedade Rows do objeto DataTable, que é justamente que o método ADDAUTORESRow na implementação do seu código faz. row.NOME = txtNome.Text; Nas duas últimas linhas seguintes são comitas as alterações no objeto DataTable forma de adicionar um objeto DataRow na//Outra base de dados. dsDados.AUTORES.Rows.Add(row); //Comitando os dados taAutores.Update(dsDados.AUTORES); //comita todas as mudanças realizadas no objeto DataTable dsDados.AUTORES.AcceptChanges(); 5.6 - Código para o evento Click do botão de pesquisar: btnPesquisar try{ /* * Aqui estamos usando o componente BindingSource para filtrar os dados em mémoria que estão * armazenados no componente DataTable * **/ if (txtPesquisa.Text == "") { //Removendo o filtro bsAutores.Filter = ""; //Atualizando o DataTable com o contéudo da base de dados this.taAutores.Fill(this.dsDados.AUTORES); } else { if (cbCampo.SelectedIndex == 0) bsAutores.Filter = "[CODAUTORES] = " + txtPesquisa.Text; if (cbCampo.SelectedIndex == 1) bsAutores.Filter = "[NOME] LIKE '%" + txtPesquisa.Text + "%'"; } }catch(Exception ex){ MessageBox.Show("Erro ao consulta \n" + "Causas do erro: " + ex.Message); } A pesquisa é realizada nos dados em memória através da propriedade Filter componente BindingSource. Nas linhas inicias da pesquisa é verificado se o usuário passou algum valor, caso não tenha passado a propriedade Filter é limpa é o método Fill do componente TableAdapter é chamado para preencher novamente o objeto DataTable com os dados da base de dados. if (txtPesquisa.Text == "") { //Removendo o filtro bsAutores.Filter = ""; //Atualizando o DataTable com o contéudo da base de dados this.taAutores.Fill(this.dsDados.AUTORES); } Para filtrar os dados é bem simples, passamos apenas os mesmos else utilizados em consulta SQL. .............. filtros ……………………. else { if (cbCampo.SelectedIndex == 0) //Campo código bsAutores.Filter = "CODAUTORES = " + txtPesquisa.Text; if (cbCampo.SelectedIndex == 1) //Campo Nome bsAutores.Filter = "NOME LIKE '%" + txtPesquisa.Text + "%'"; } 5.7 - Código para o evento DoubleClick do componente DataGrid: grdDados try{ //Capturando o indíce da linha selecionada da grid int linha = grdDados.CurrentRowIndex; row = (DADOSDataSet.AUTORESRow)dsDados.AUTORES.Rows[linha]; TrataBotoes("editar"); //Selecionando a guia Dados tbDados.SelectedIndex = 0; } catch(Exception ex){ MessageBox.Show("Houve um erro ao selecionar a linha atual. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } O código definido no evento DoubleClick do componente DataGrid é bem simples, A principal função é permitir que o usuário selecione o registro com um duplo clique exiba a guia de dados para o usuário alterar o registro. Primeiro é capturado o indíce da linha selecionada no objeto grdDados (DataGrid) com a propriedade CurrentRowIndex, para que seja possível recuperar a instância do componente DataRow. int linha = grdDados.CurrentRowIndex; Veja que o cast é nessário pois o objeto row é uma instância da classe AUTORESRow, já que a propriedade Rows do objeto DataTable, mantém uma lista de objetos genericos. row = (DADOSDataSet.AUTORESRow)dsDados.AUTORES.Rows[linha]; Chamanos o método TrataBotões com o valor “editar” para indicar que queremos alterar o registro é somente os botões cancelar e salvar devem ficar habilitados. E por é selecionado a guia Dados no formulário tbDados.SelectedIndex = 0; 5.8 - Código para o evento Click do menu Voltar: mnuVoltar //Retornando a linha selecionada DataRow dataRow = null; if (bsAutores.Position >= 0) dataRow = dsDados.AUTORES.Rows[bsAutores.Position]; else dataRow = row; if (dataRow != null) { //Verificando se a linha foi criada ou modificada mais não salva if ((dataRow.RowState == DataRowState.Detached) || dataRow.RowState == DataRowState.Unchanged)) { if (MessageBox.Show("A dados não salvos. Deseja continuar?", "Atenção", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { try { //Desfazendo as autoreções dsDados.AUTORES.RejectChanges(); this.Close(); } catch (SqlCeException ex) { MessageBox.Show("Houve um erro ao desfazer as alterações. \n" + "Causas do erro: " + ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } } } else this.Close(); } else this.Close(); 5.9 – Testando o Cadastro de autores Depois de implementar o formulário de cadastro de autores agora podemos testar. Acesse o formulário FrmPrincipal é de um duplo clique sobre o menu “Autores”, e implemente 5.9.1 - Código para o evento Click do menu Autores: mnuAutores FrmCadAutores autores = new FrmCadAutores(); autores.ShowDialog(); Implemente também o seguinte código no menu “Sair” 5.9.2 - Código para o evento Click do menu Sair: mnuSair //Finalizando o aplicativo if (MessageBox.Show("Deseja finalizar o aplicativo ?", "Atenção", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes){ Application.Exit(); } Até este ponto finalizamos o cadastro de autores, definimos sua chamado no menu Autores no formulário principal e também implementamos um código no menu “Sair” para que possamos finalizar a aplicação através do método Exit() da classe Application. Teste o aplicativo pressionando F5 ou selecionando o menu Debug -> Start Debugging.