Você está na página 1de 84

Este artigo trata da criao, em Windows Forms, usando C# e SQL Server de um sistema simples

de um consultrio mdico com cadastro de pacientes, mdicos e consultas.


Comece abrindo o SQL Server e crie um novo database com o nome Consultorio. Aps isso crie
as tabelas de Pacientes, Mdicos e Consultas, conforme mostra a imagem abaixo:

Agora preciso criar os relacionamentos entre as tabelas. Para isso, no Solution Explorer, clique
com o boto direito na tabela Consulta recm criada, clique em Design, depois nos botes do
menu clique em Relationships, como mostra a imagem:

Na janela que surge, clique no boto Add, abra a aba Tables and Columns Specification e clique
no boto ao lado:

Na janela que abre, em Primary key table, faa os relacionamentos, escolhendo a Coluna Medico
e abaixo relacione o IDMedico da tabela Medico com o IDMedico da tabela Consulta. Faa isso
tambm com a tabela Pacientes:

Aps isso, salve a tabela, ir aparecer uma mensagem avisando que as alteraes feitas se
aplicaro nas demais tabelas, clique em Sim e aguarde.
Agora abra o Visual Studio, crie um novo projeto Windows Forms e d o nome de Consultas:

Ser gerado um formulrio, ele ser nosso form principal, clique nele, abra a janela Properties
(CTRL+W+P) altere as seguintes propriedades:
- Text coloque o nome Consultas
- (Name) altere para frmPrincipal
- WindowState altere para Maximized, para abrir sempre maximizado
- MaximizeBox false
- MinimizeBox false para que s aparea o boto de fechar no form
- KeyPreview true, para ativar o uso do teclado nos eventos do form
2

Seu form dever ficar parecido com o da imagem abaixo:

Agora abra a janela Toolbox (CTRL+W+X) e arraste da aba Menus & Toolbars um Toolstrip, que
nada mais do que uma barra de controles para seu form. Clique no boto ao lado dele,
selecione

controle Button,

clique

com

boto

direito

nele

clique

em DisplayStyle > ImageAndText. Seu form dever ficar assim:

Agora vamos adicionar um novo Data Source, para isso, clique no menu Data > Add New Data
Source. Na janela que aparece, selecione Database e clique em Next. Essa parte do exemplo
bem parecida com a que ensinei na 1 parte do artigo de Acesso a Dados, postada dias atrs.
Clique em New Connection, selecione em Server Name, o servidor local do seu pc, se estiver
com dvidas quanto a isso, apenas digite (local)\SQLEXPRESS (lembrando que este exemplo
usa a verso Express do SQL Server), selecione o Database Consultorio, criado anteriormente,
clique em OK, em Next, altere o nome de sua connectionstring para strConsultorio, clique em
Next e aguarde. Na prxima tela ser perguntado quais objetos voc deseja adicionar ao seu
DataSet, clique em Tables, altere o nome do seu DataSet se quiser e clique em Finish. primeira
vista, parece que nada aconteceu, mais se voc abrir a janela Solution Explorer (CTRL+W+S) ou
clicar em Data > Show Data Sources (SHIFT+ALT+D) ver que nosso DataSet foi criado com
sucesso:

No Solution Explorer, clique no nosso projeto com o boto direito e clique em Add > Windows
Form. D o nome de frmMedico e clique em OK.
Altere a propriedade Text para Cadastro de Mdicos e na janela Data Sources que vemos na
imagem acima, repare que nossas tabelas trazem os controles adequados a elas, como por
exemplo, se voc expandir a tabela Medico, e clicar em IDMedico ver que podemos usar um
Textbox, um Label, etc. Isso feito automaticamente pelo prprio Visual Studio, ele mapeia os
dados que vem do banco SQL e nos mosta quais os controles mais adequados cada coluna:

Altere o controle Label para o campo IDMedico como mostra a imagem acima. Agora arraste a
tabela Medico para nosso form que ele cria automaticamente a estrutura necessria para inserir
dados em nosso form. Faa os ajustes necessrios nos campos como mostra a imagem:

Agora volte ao formulrio principal, d dois cliques no controle ToolStrip que adicionamos a ele
ou aperte F7 para ir ao evento toolStripButton1_Click e insira o seguinte cdigo:
4

O que fiz no cdigo acima foi instanciar o formulrio mdico e fazer a chamada a ele por meio do
mtodo ShowDialog().
Agora compile o projeto e veja o resultado:

Experimente inserir, salvar e excluir registros, pare a compilao e compile de novo e note que
os registros so salvos no banco e esto disponveis para posterior consulta. Assim, encerramos
aqui a 1 parte da srie de artigos de Windows Forms com acesso dados.
Nesta 2 parte do artigo de criao de um sistema simples de um Consultrio Mdico
faremos o Cadastro de Pacientes e Consultas.
Abra seu projeto no Visual Studio e abra o modo design do Cadastro de Mdicos. Iremos
aplicar algumas configuraes que sero padronizadas, ou seja, sero aplicadas todos os forms
para que sigam um determinado padro.
Abra a janela Properties (CTRL+W+P ou F4) e altere as propriedades:
- Text na seleo de registros of {0} altere para de {0}
- FormBorderStyle altere para FixedSingle para que o form no possa ser redimensionado
- Start Position coloque CenterScreen para que o form abra no meio da tela
- MaximizeBox false
- MinimizeBox false para que s aparea o boto de fechar no form
- KeyPreview true, para ativar o uso do teclado nos eventos do form
Seu form dever ficar com propriedades iguais ao do form principal.
5

Agora clique no formulrio e aperte F7 para ir pgina de cdigo e note que, a partir do
momento em que foi adicionado o DataSet e seus demais controles, o Visual Studio
automaticamente adicionou tambm cdigos ao nosso form:

Vamos fazer uma verificao simples para que, se o usurio apertar a tecla ESC, feche o
formulrio. Para isso, na janela propriedades do form Medico, v nos eventos e d dois cliques no
evento KeyDown. Ir se abrir a tela de cdigos, nela insira o cdigo abaixo:

No cdigo acima fiz a verificao se a tecla digitada foi ESC, se foi, automaticamente o form
fechado. Se no, nada acontece. Simples assim.
Cadastro de Pacientes Vamos criar agora um novo form. Na Solution Explorer, clique com o
boto direito no projeto, clique em Add > Windows Form e d o nome frmPacientes.
Neste form, aplique as configuraes padronizadas que definimos no comeo do artigo. D o
nome de Cadastro de Pacientes esse novo form. Agora abra o evento KeyDown deste form e
aplique o mesmo cdigo do anterior, para que, quando o usurio apertar a tecla ESC, o form
feche automaticamente.
Vamos configurar nosso data source. Para isso, abra a janela Data Sources (SHIFT + ALT + D),
clique no boto ao lado de Paciente e troque o formato dele para Details, como mostra imagem a
seguir:

Expanda a tabela Paciente e troque o formato do IDPaciente para Label, da mesma forma como
fizemos no artigo anterior. Aps isso, arraste a tabela Paciente para o form recm-criado:

Altere algumas propriedades de seu form para que o mesmo fique padronizado como os outros,
parecido com o da imagem abaixo:

Agora vamos ao form principal, adicionar outro boto para fazer a chamada este form que
criamos. No form principal, clique no boto de Cadastro de Mdicos, ir aparecer outro boto ao
lado, clique nele e clique em Button. Agora clique com o boto direito no boto recm criado, e
clique em DisplayStyle > ImageAndText, como a figura abaixo nos mostra:

D o nome ao Button de Cadastro de Pacientes. D um duplo clique neste boto para fazer a
chamada nele ao form de Pacientes:

O que fiz acima foi o mesmo feito no boto do Cadastro de Mdicos: instanciei o formulrio
paciente e usei o mtodo ShowDialog para exibir o formulrio no evento Click do boto.
Experimente adicionar alguns registros para testar as funcionalidades que o Visual Studio nos
fornece com apenas alguns cliques, como se pode ver, no nada muito complexo de ser feito.
Agora no form de Cadastro de Mdicos, adicione um separador (Separator), mais um boto, por
meio das opes do ToolStripButton e, neste novo boto, clique com o boto direito nele e clique
em DisplayStyle > Text. Agora clique neste boto, abra as propriedades do seu form, v a
propriedade Text e digite Fechar, como mostra a imagem abaixo:

D dois cliques neste boto e insira o mtodo Close, como mostra a imagem abaixo:

Faa isso aos demais formulrios, mantendo aquela idia de criar uma padronizao aos forms.

Cadastro de Consultas Crie um novo form e d o nome de frmConsulta. Aplique as


configuraes padronizadas que definimos no incio do artigo, clique no evento KeyDown do form
e insira novamente o cdigo para que o form se feche quando o usurio teclar ESC.
Abra a janela Data Sources (SHIFT + ALT + D), clique no boto ao lado de Consulta e troque o
formato dele para Details, como fizemos anteriormente.
Agora expanda a tabela Consulta e troque o formato do IDConsulta para Label, IDMedico troque
para um ComboBox para que o usurio possa escolher qual mdico ser mostrado no momento
da consulta e faa o mesmo para a coluna IDPaciente. E na coluna Ativo, deixe como None,
porque no precisaremos mostrar esta coluna ao usurio, ela servir para controle interno, para
sabermos se tal consulta est ativa ou no.
Aps isso, arraste a tabela Consulta para o form recm-criado:

Altere as propriedades do form para que fique igual ao da imagem abaixo:

No combo Nome do Mdico e Nome do Paciente, altere a propriedade DropDownStyle para


DropDownList, para que o usurio no possa digitar nos combos. No combo Data, altere a
propriedade Format para Custom e a propriedade CustomFormat para dd/MMM/yyyy. Nos
combos Incio e Trmino,

altere

propriedade Format para

Custom

propriedade CustomFormat para HH:mm. Assim voc coloca um valor personalizado tanto para
data quanto para hora. No textbox Observaes, altere a propriedade Multiline para True, para
9

deix-lo com vrias linhas para inserir as observaes. As demais configuraes seguem o
padro dos outros forms.
Agora volte ao form principal, adicione um novo boto, d dois cliques nele e faa a chamada ao
formulrio de Consulta por meio do cdigo seguinte:

Agora, se compilarmos nosso sistema, veremos que o form de Consulta no nos retorna
absolutamente nada nos combos de Mdico e Paciente.

Isso acontece porque no relacionamos as respectivas tabelas aos combos. Para fazer isso, abra
a janela Data Sources (SHIFT + ALT + D) e arraste a tabela Mdicos para o seu respectivo
combo. Faa o mesmo com a tabela Paciente. Aps isso, podemos clicar ao lado do combo, na
setinha e percebermos que ele arrasta os dados referentes ao mdico para este combo:

Agora rode o sistema e tente adicionar uma nova consulta.Poder ocorrer dois erros, ou esse:
10

A imagem esquerda mostra o erro, que diz que a Data no permite valores nulos, para arrumar
isso, s inserir a data como mostra imagem a direita, selecionando o campo combo e clicando
no quadrado vermelho. Independente do primeiro erro, obrigatoriamente ir ocorrer o erro abaixo:

Dizendo que a coluna Ativo no permite valores nulos. Para arrumar s abrir o SQL Server,
onde foi criado nossas tabelas, clicar com o boto direito na tabela Consultas, clicar em Design e
selecionar o checkbox na coluna Allow Nulls do campo Ativo, como mostra a imagem abaixo:

Ainda no terminou! importante salientar que, quando feita alguma alterao no banco de
dados, como essa que fizemos, devemos realizar a alterao tambm em nosso DataSet.
Para isso, salve, volte ao Visual Studio, abra o Solution Explorer, d dois cliques no
seu ConsultorioDataSet, clique na coluna Ativo, abra a janela Properties e, na opo Allow
DBNull, troque para True:

11

Salve, rode seu projeto e adicione um novo registro:

De incio, vamos alterar as imagens dos menus do form principal. Para isso, abra o form, clique
nos botes do menu, se no tiver dado nome a eles, aproveite e j d o nome de Mdicos,
Pacientes e Consultas. Agora pesquise no Google Imagens as respectivas imagens para cada
boto, salve em seu pc, clique em cada boto e, no menu Propriedades, clique no boto ao lado
do atributo Image e clique em Import, como mostra a imagem abaixo:

Use de preferncia imagens com tamanho mximo de 48x48. Aps inserir as imagens clique no
atributo ImageScaling e o deixe como None para a imagem ficar com o tamanho real. Se a
imagem no ficar transparente, s alterar a propriedade ImageTransparentColor para a cor da
sua imagem.
Podemos alterar nosso menu de navegao para que fique, por exemplo, esquerda de nossa
janela e no em cima. Por meio da propriedade Dock podemos fazer isso, como mostra a imagem
abaixo:
12

Ok, no meu exemplo vou deix-lo no topo mesmo, mais se preferir pode alterar a propriedade
Dock como mostrou a imagem.
A princpio, nosso formulrio est pronto. Com cadastros e funcionalidades simples, nos deu
uma boa viso de como fcil trabalhar com os controles do Visual Studio.

Agora imagine o seguinte cenrio: uma aplicao dessa feita para a vida real onde, no cadastro
pacientes, no so 5 nem 10 nem 100 e sim 1000 registros.
Como ficaria se precisarmos navegar no registro 999, por exemplo? Iriamos de um em um?
Ficaria complicado, concordam? Por isso digo que at o momento montamos um sistema o mais
simples possvel.
A partir de agora iremos mudar nosso foco e simular uma aplicao de verdade, para um
potencial cliente, utilizando alguns conceitos da Programao Orientada Objetos, como a
Herana.
De forma simplista o conceito de Herana significa que uma ou mais classes filhas herdam
atributos e mtodos da classe pai (conhecida tambm como classe base). A herana usada com
a inteno de reaproveitar o cdigo e assim garantir uma alta produtividade em nosso sistema.
Vamos trabalhar tambm em nosso sistema com o conceito de Parametrizao, que o conceito
de implementar detalhes e parmetros ao sistema de acordo com as necesssidades do cliente.
Seguindo este conceito, no teremos mais um formulrio como o de Pacientes, com os botes

13

avanar e retroceder os registros, pois quando abrirmos o form de Pacientes, no queremos ver
todos os Pacientes e sim ver determinado Paciente.
Ser feito assim em todos os formulrios, por meio do conceito de Herana. Teremos tambm
um formulrio de pesquisa. Comecemos ento nosso formulrio base principal que ser o
formulrio pai:
Clique em Add > Windows Form, d o nome de frmBase e clique em OK.
Ser gerado nosso formulrio, clique nele, abra a janela Properties (F4) e altere as seguintes
propriedades:
- Start Position coloque CenterScreen para que o form abra no meio da tela
- MaximizeBox false
- MinimizeBox false para que s aparea o boto de fechar no form
- KeyPreview true, para ativar o uso do teclado nos eventos do form
- FormBorderStyle altere para FixedDialog para que o form no possa ser redimensionado
Agora vamos inserir os controles que sero padres nos demais forms. Arraste uma ToolStrip de
nossa Toolbox para o form e insira 4 botes, 1 separador e mais 1 boto, nessa ordem referentes
aos botes Novo, Salvar, Excluir, Localizar e Fechar conforme mostra a imagem abaixo:

Altere a propriedade DisplayStyle para Image and Text dos botes, a propriedade ImageScaling
para None e insira imagens para os botes referentes como fizemos no form anterior. Altere
tambm a propriedade Design dos botes para podermos identific-los mais facilmente quando
formos

us-los

na

programao.

Na

ordem

altere

para btnNovo, btnSalvar, btnExcluir, btnLocalizar e btnFechar. Adicione o controle StatusStrip a


seu form, nele adicione um StatusStripLabel, d o nome de lblMensagem e deixe a
propriedade Text em branco para que possamos configurar via cdigo uma mensagem ao usurio
quando ele realizar determinada ao.
14

Clique com o boto direito no seu form e clique em View Code ou simplesmente aperte F7 para ir
a pgina de cdigos. Nela, vamos criar um enumerador, com os itens Inserindo, Navegando e
Editando, e criaremos uma varivel privada deste enumerador para sabermos qual o status do
sistema, se por exemplo o usurio estiver inserindo, devemos desabilitar o boto de excluir, ou
quando estiver localizando, devemos desabilitar o boto de salvar.
Desta forma estaremos otimizando nosso cdigo e evitando erros do usurio. A imagem abaixo
mostra nosso cdigo:

Vamos voltar ao nosso form, no modo visual e implementar o cdigo para o boto Fechar, como
parte de nosso exemplo. Primeiro d dois cliques em cima do boto de fechar e chame o
mtodo Close(). Depois, volte ao form, abra a janela de propriedades do mesmo, clique nos
Eventos, selecione o evento KeyDown, d dois cliques nele e insira o cdigo abaixo para que o
form se feche ao apertar ESC.

Usando esse conceito de Herana em nosso sistema, s utilizaremos este cdigo acima apenas
uma vez e os demais herdaro as funcionalidades do formulrio base, o que melhora nosso
Devemos ter a preocupao de, depois que o usurio gravar um registro por exemplo, os
controles usados, como combobox, textbox e outros, sejam limpados automaticamente. Para isso
devemos criar um mtodo que limpa os campos aps a gravao de um registro qualquer.
Abra o frmBase.cs e crie um novo mtodo do tipo private com o nome LimpaControles que no
ir nos retornar nada, como mostra a imagem abaixo:
15

Acima fiz um lao do tipo foreach na classe nativa Control (pertencente ao namespace
Windows.Forms) com o objetivo de ser feita uma varredura em meu formulrio, percorrendo
todos os controles existentes dentro do meu form. A primeira verificao, por exemplo, foi pra
saber se existe um textbox em meu form e, se existir, ele ser limpado. E assim fao com os
demais. Lembrando que em alguns controles, como Label e Button, no tem necessidade de
serem limpos. Conforme voc for precisando adicionar ou substituir um controle por outro s
adicionar o tipo dele em nosso foreach.
Se precisarmos fazer o mesmo a um controle do tipo CheckedListBox, devemos fazer outro
foreach, como mostrou nosso ltimo if da imagem acima.
Continuando com nosso conceito de trabalhar com Herana, iremos criar os mtodos Salvar,
Excluir e Localizar apenas neste formulrio base, e iremos fazer a chamada desses mtodos nos
demais formulrios, poupando assim o retrabalho de ter que digitar o mesmo mtodo diversas
vezes. Iremos comear criando o mtodo Salvar.

16

Acima criei o mtodo do tipo booleano passando como retorno o valor false, ele s me
retornar true quando o registro for salvo no banco. Fao o mesmo com os mtodos Excluir e
Localizar.
Agora v ao modo design do formulrio base e d dois cliques nos botes Salvar e Excluir.
Dentro deles insira o seguinte cdigo:

O que fiz foi chamar os mtodos referentes aos respectivos botes e dependendo da resposta do
mtodo entro no meu if ou no meu else. Em minhas verificaes coloquei o mtodo
LimpaControles, pois ele ir entrar verificar se o registro foi gravado, por exemplo, se foi ele limpa
os controles e exibe a mensagem ao usurio, ou que o registro foi gravado ou que deu erro, isso
dependendo do que acontecer em nosso sistema.
Uma caracterstica que ser implementada a de que quando forem abertos os formulrios
sempre viro registros vazios, ou seja, se desejar um registro especfico, o usurio ter que
localizar o mesmo por meio do respectivo boto. Depois de salvo um registro, por exemplo, eles
so automaticamente limpados.
Vamos agora implementar o enum que criamos no artigo anterior, em nosso boto Salvar. Se o
usurio salvou o registro ou excluiu, devemos configurar nosso enum para Navegando, como
mostra a imagem a seguir:

Devemos tambm dentro desses mtodos fazer a chamada a outro que iremos criar para que os
controles sejam habilitados ou desabilitados.
17

Agora vamos criar os mtodos para os botes Novo e Localizar que so iguais com os dos
botes Salvar e Excluir, como voc pode perceber na imagem:

Lembrando que aps criarmos nosso mtodo que habilita/desabilita os controles do form
devemos implement-lo aos botes Novo e Localizar.
Vamos criar um mtodo que ser implementado nos formulrios que herdaro de meu formulrio
base, que ser o CarregaValores, a funo dele ser a de retornar os dados parametrizados do
banco e carregar meus controles, vou dizer que, por exemplo, o campo txtNome ir vir carregado
com a coluna de nomes do meu banco e assim por diante. Faa a chamada a este mtodo no
boto Localizar.
Crie um novo mtodo do tipo public virtual como os anteriores s que ele ser do tipo void, ou
seja, no ter retorno algum. Crie tambm o mtodo para habilitar / desabilitar os controles no
form, como a imagem abaixo nos mostra:

O que fiz foi um foreach, que percorre todos os meus controles, parecido com os do
mtodo LimpaControles. S que aqui ele faz um if pra verificar se o controle um Toolstrip, se for
ele continua, se no for, ele habilita nossa varivel bValue que foi passada como parmetro em
nosso mtodo.
Agora dentro deste mesmo mtodo, fao as verificaes em meus botes para habilit-los ou
desabilit-los.

18

Acima fiz o seguinte: passei o status de cada boto, por exemplo, no primeiro boto, o Novo,
atribui ele que o status ser o Navegando e assim fiz com os demais. No fim atribui que o boto
Fechar sempre estar habilitado. Assim, dependendo da ao do usurio o boto especfico
estar habilitado ou desabilitado (com exceo do Fechar que ter valor fixo).
Agora s aplicar os mtodos aos respectivos botes passando os valores, true ou false,
dependendo de cada situao. Por exemplo, no boto novo, passo meu mtodo com o valor true,
porque quero habilitar os controles para que o usurio insira um novo registro, j no boto excluir,
passo o valor false ao meu mtodo porque j exclui, no preciso mais que os controles sejam
habilitados e assim sucessivamente. Abaixo um exemplo do boto Localizar:

Finalizando, v ao modo Design de nosso form e d dois cliques no form para ir ao


evento Load do mesmo. Nele, insira os seguintes cdigos:

Fazendo isso, toda vez que o form for carregado ele iniciar com o status Navegando, com os
controles limpos e com o mtodo HabilitaDesabilitaControles como false. Assim inicializamos os
19

mtodos em nosso form de uma forma prtica e sem erros, permitindo ao usurio praticidade e
performance na hora de navegar nos formulrios.
Ol pessoal, continuamos nossa srie de artigos criando aplicaes simples em Windows Forms
usando a linguagem C# e o banco de dados SQL Server.
Nesta parte vamos montar nossa tela base de pesquisa, que ser parametrizada, ou seja, nos
retornar apenas o que pesquisarmos e no toda a nossa base de dados, o que em uma
aplicao real nos traria muita dor de cabea se no fosse usado o recurso de parametrizao
que estamos implementando. Nossa tela de pesquisa ser tambm genrica. Montaremos a tela
padro e, a partir dela, sero montadas as telas herdadas que forem necessrias no decorrer de
nossos artigos. Com isso ganharemos e muito em performance em nosso sistema.
Abra sua solution e clique em Add > New Windows Form. D a ele o nome de frmPesquisaBase,
pois este ser o nosso formulrio base de Pesquisa.
Ser gerado nosso formulrio, clique nele, abra a janela Properties (F4) e altere as seguintes
propriedades:
- Start Position coloque CenterScreen para que o form abra no meio da tela
- MaximizeBox false
- MinimizeBox false para que s aparea o boto de fechar no form
- KeyPreview true, para ativar o uso do teclado nos eventos do form
- FormBorderStyle altere para FixedSingle (faa o mesmo nas propriedades do formulrio Base)
- ShowInTaskbar false, para no mostrarmos o form no taskbar
Adicione o controle StatusStrip a seu form (da mesma forma como fizemos no formulrio base) ,
nele adicione um StatusStripLabel, d o nome de lblMensagem e deixe a propriedade Text em
branco para que possamos mostrar ao usurio qual foi a quantidade de registros retornados aps
ele ter feito uma pesquisa.
Nosso formulrio ter duas formas de pesquisar: ou pelo cdigo do usurio, ou pela descrio.
Vamos adicionar um GroupBox ao nosso form e dar o nome de Tipo de Pesquisa, como mostra a
imagem a seguir:

20

Agora dentro dele adicione dois RadioButton com as propriedades Text Cdigo e Descrio.
Altere o ID de cada um deles para rbtCodigo e rbtDescricao, respectivamente e deixe a
propriedade Checked do RadioButton Descrio setada para True, para que o form sempre
inicialize com ele checado, que o mais comum de se pesquisar.
Adicione tambm, ao lado do GroupBox, um Label, um TextBox e um Button, para que o usurio
possa

digitar

no

campo

descrio

referente

ao

usurio.

Altere

ID

deles

para lblDescricao, txtPesquisar e btnPesquisar. Deixe seu form como o da imagem abaixo:

Agora adicione dois botes no canto inferior direito do seu form, um que o boto OK e outro o
boto Fechar. D dois cliques no Fechar e chame o mtodo Close. A esses botes sete a
propriedade DialogResult de cada um como OK e Cancel, respectivamente, como mostra a
imagem a seguir:

21

Agora abra o evento KeyDown do seu form e coloque aquela verificao para que, quando o
usurio pressionar ESC ou ENTER, o form se feche. Sete o valor do DialogResult para Cancel,
como mostra a imagem abaixo:

Agora vamos implementar um ListView ao nosso formulrio. Ento abra a Toolbox, arraste um
controle ListView ao form e d a propriedade ID o nome lstPesquisa. Ainda nas propriedades,
altere a propriedade View para Details e abra a opo Columns para adicionar duas colunas ao
nosso ListView. Clique em Add e altere a propriedade Text para Cdigo, faa o mesmo na
prxima, d o nome Descrio e clique em OK. Redimensione sua coluna Descrio se desejar.
Altere a propriedade FullRowSelect para True para que, quando o usurio clique no campo
Descrio, por exemplo, seja selecionado toda a linha e no s o campo clicado. Altere para True
tambm a propriedade GridLines, para que nosso ListView fique com as linhas do Grid.
Finalizando o design de nosso ListView, altere a propriedade MultiSelect pra False, porque
queremos que seja selecionado apenas uma linha de nosso grid e no vrias. Se voc alterou as
propriedades como descrito, seu ListView deve estar parecido com o da imagem a seguir:

Vamos implementar as funcionalidades de nosso ListView entrando na pgina de cdigos do


formulrio. Vamos criar uma classe pblica do tipo string e a inicializaremos com um valor vazio,
para que ela seja preenchida em outras partes de nosso cdigo, como quando o usurio escolher
um cdigo em nossa Grid e clicar em OK ou mesmo quando ele der dois cliques no Grid. Vejamos
o cdigo:
22

Agora volte ao modo Design do form e d dois cliques no boto OK. Insira o seguinte cdigo:

O que fizemos no bot OK tivemos que fazer tambm no evento SelectedIndexChanged do


ListView s que usamos um Try/Catch para tratar um erro que no da aplicao e sim do
prprio controle. No evento DoubleClick do ListView devemos usar o cdigo para preencher
nossa varivel e adicionarmos o mtodo Close e o DialogResult com o valor OK, como fizemos
no evento KeyDown do formulrio anteriormente. A imagem a seguir mostra nosso mtodo:

Dessa forma, capturamos praticamente todas as opes que o usurio tem no momento em que
vai pesquisar. Seja no clique duplo no resultado da pesquisa, seja no boto OK, seja quando o
foco est na pesquisa do usurio.
Vamos comear criando nosso mtodo de Pesquisa, no arquivo de cdigos de nosso formulrio
de Pesquisa crie um mtodo do tipo pblico virtual e que no ir ter retorno (void). No iremos
implementar nada neste mtodo, j que sero implementados apenas nos formulrios herdados.
Ou seja, em cada formulrio de pesquisa ter uma implementao diferente, como a pesquisa de
clientes, por exemplo.
23

Agora vamos ao modo Design de nosso formulrio. Quero que meu boto de Pesquisa seja
chamado quando o usurio digitar algo na caixa de pesquisa e der um ENTER. Ou seja, este ser
o

boto

padro

de

nosso

form.

Para

isso,

clicamos

em

nosso

form

e,

na

propriedade AcceptButton, escolhemos nosso btnPesquisar, como a imagem abaixo nos mostra:

D dois cliques no boto Pesquisar para voltarmos pgina de cdigos de nosso form. No
evento Click desse boto chame o mtodo Pesquisar, faa a configurao de nossa StatusStrip,
que criamos anteriormente, para retornar ao usurio quantos registros foram encontrados em
cada pesquisa que for feita e adicione outras implementaes, como mostrado na imagem
abaixo:

Alm das implementaes citadas acima, como voc pode ver na imagem, adicionamos mais
duas verificaes, uma que habilita o boto OK de nosso form se a propriedade Count for maior
que 0, ou seja, se nosso ListView nos retornar ao menos 1 registro em nossa pesquisa, e a outra
que, se o boto OK estiver habilitado, faz com que nosso ListView ganhe o foco. Esta ltima
necessria porque, assim o usurio pode navegar entre os registros usando as setas do teclado,

24

dando duplo clique para ver determinado registro por exemplo e assim estaremos evitando ao
mximo possvel erros do usurio.
Agora vamos criar um mtodo que ir carregar o retorno de nossa pesquisa da base de dados
em nosso ListView. Crie o mtodo do tipo pblico void e que ter como parmetro um DataTable,
que ser implementado em nossos formulrios que herdaro do formulrio base. Veja o mtodo a
seguir:

Com este mtodo, finalizamos nossos mtodos do formulrio de Pesquisa, agora volte ao modo
Design, clique nos Radio Buttons Cdigo e Descrio, v ao evento Click, d dois cliques e insira
o seguinte cdigo:

Apenas para que o usurio tenha uma maneira rpida e fcil de pesquisar, melhorando assim a
eficincia de seu sistema e a usabilidade do mesmo.
Lembrando que para cada formulrio de pesquisa, teremos dois tipos de pesquisa: por cdigo ou
por descrio. Com isso em mente, iremos criar um novo DataSet e deixaremos de lado o que foi
criado em artigos anteriores, pois nele usamos as facilidades do Visual Studio para cri-lo, j
nesse estamos usando um outro tipo de abordagem, tendo como base o conceito
de Programao Orientada Objetos. Dito isto, abra a Solution Explorer (CTRL+W+S), clique em
seu projeto com o boto direito e clique em Add > New Item. Escolha no menu Categories a
opo Data, no menu Templates escolha DataSet, d o nome dsConsulta e clique em OK.

25

Ser um DataSet igual ao nosso criado nas primeiras aulas, a diferena que desta vez no
iremos usar o menu DataSources para arrastar as tabelas. Vamos arrastar diretamente do banco
por meio do Server Explorer, assim ele criar para ns cada DataTable e DataAdapter referentes
s respectivas tabelas para que possamos customiz-las.
Ento abra o Server Explorer (CTRL+W+L), expanda seu Database Consultorio, seu menu
Tables arraste as tabelas para o DataSet recm criado. Seu DataSet dever ficar como o da
imagem abaixo:

Vamos customizar a tabela de mdico para criar mais duas pesquisas, uma por cdigo e outra
por nome/descrio. Para isso, clique com o boto direito no MedicoTableAdapter da
tabela Medico e clique em Add Query. Ir abrir um wizard que nos perguntar como nossa query
ir acessar o banco, existem trs opes: por meio de instrues SQL, por meio da criao de
uma Stored Procedure ou por meio do uso de uma Stored Procedure existente. Neste caso,
escolha a 1 opo e clique em Next.

26

Na prxima tela, devemos informar qual tipo de consulta iremos realizar dentre cinco opes: se
ser por meio de um SELECT que retornar vrios registros, se ser por um SELECT quer
retornar apenas 1 registro, se iremos usar a instruo UPDATE, que atualiza os dados, se
iremos usar a instruo DELETE, que apaga os dados ou se ser por meio da instruo INSERT,
que insere os dados. Escolha a 1 opo e siga em frente.

Aqui ele j me traz a instruo SQL pronta. Note o boto Query Builder, com ele podemos fazer
instrues mais complexas, com o uso de Join, Group By, etc. Como a nossa consulta ser
parametrizada, volte a instruo SQL e altere a instruo passando o parmetro como mostra a
imagem a seguir:

Nesta tela, devemos escolher quais mtodos devemos usar em nosso TableAdapter. A 1
opo, Fill a DataTable, como o prprio nome diz, preenche o DataTable e a 2 opo, Return a
DataTable, apenas retorna o DataTable preenchido. Podemos usar os dois, mais neste exemplo
(como estou seguindo risca as videoaulas de Luciano Pimenta) iremos escolher somente a 1
opo e dar o nome dePesquisaID.

27

A prxima tela mostra que o Wizard gerou a instruo SQL e o mtodo de preenchimento. Clique
em Finish. Perceba na imagem abaixo que foi criada nossa query parametrizada, ou seja, ela
pede como parmetro o ID do Mdico:

Agora crie um Wizard igual esse que criamos, apenas mude nossa instruo SQL, j que nesse
pesquisaremos pelo nome. Como podemos pesquisar por apenas uma parte do nome, use a
clusula Like, como a imagem abaixo nos mostra:

Na prxima tela, selecione o mtodo Fill e d o nome PesquisaNome. Pronto, agora temos as
duas consultas criadas. Agora vamos fazer um teste.

28

Primeiramente, d um Build Solution (F6) na sua aplicao. Agora abra o Form1.cs e adicione o
seguinte cdigo:

Fiz a chamada a meu DataSet por meio do using e, no mtodo Load do meu formulrio,
instanciei o MedicoDataTable, instanciei o MedicoTableAdapter, que foi na onde criei minhas duas
pesquisas e, por meio dele, fiz a chamada ao mtodo PesquisaID, referente pesquisa criada
passando como parmetro meu MedicoDataTable e um valor inteiro qualquer, nesse caso o 1. Por
meio do meu mtodo Rows, tenho acesso a coluna da minha tabela Medico, para isso usei o dt,
que a instncia de meu DataTable e chamei o mtodo Rows, passando como parmetro o
ndice 0, que seria o 1 registro e nome da coluna, que neste caso ID_MEDICO. Iremos fazer
basicamente isso em nossas outras consultas. Esse exemplo iremos usar em nosso Cadastro, j
a outra consulta que criamos usaremos em nosso formulrio de Pesquisa.
Finalizando, apague estes cdigos do mtodo Load desse form, j que isso nos serviu apenas de
exemplo para implementarmos nas consultas e pesquisas dos outros formulrios.
Nesta parte iremos continuar a customizao de nossas tabelas e sobrescrever os mtodos para
o formulrio de Cadastro de Pacientes. Acompanhe:
Como feito no artigo anterior, vamos criar um TableAdapter, s que desta vez para a tabela
de Pacientes. Ento, clique com o boto direito no TableAdapter da tabela Paciente e clique
em Add Query. Faa isso com os dois tipos de pesquisa, como no form de Medicos, por ID e
por Paciente. Altere a instruo SQL da consulta por ID, como mostra a imagem abaixo e clique
em Next:

29

Na prxima tela, ao invs de escolhermos a opo Fill a DataTable, vamos escolher a outra
opo, Return a DataTable, com o nome PesquisaID para vermos as diferenas. Escolha e clique
em Next, depois em Finish.

Agora crie outra query e faa o mesmo que a query anterior, s altere a instruo SQL, como a
da imagem a seguir:

Escolha o mtodo Return a DataTable e d o nome de PesquisaNome. Pronto, nosso DataSet


est concludo.
30

Agora vamos criar os formulrios que herdaro dos formulrios base que foram criados. Salve e
d um Build Solution (F6) no seu projeto para ter certeza de que o mesmo no est com erros.
Agora clique com o boto direito no seu projeto e clique em Add > New Item. No iremos
adicionar um Windows Form normal e sim um Inherited Form, que traduzindo seria um Formulrio
Herdado que, como o prprio nome diz, herdar de outro formulrio, neste caso do Paciente. D
um nome sugestivo a ele e que no seja o mesmo nome dos formulrio j criados. No exemplo
dei o nome frmPacienteHerdado. Ir aparecer outra janela perguntando de qual form iremos
herdar, escolha o frmBase, que o que tem todas as caractersticas que precisamos, e clique em
OK. Como voc pode notar abaixo, temos os mesmos controles do frmBase, o que precisamos
fazer no momento adicionar alguns controles.

Adicione 4 labels e 2 textboxs, deixe o label que ficar em cima do textbox sem nome, pois ele
ser preenchido com os dados que vierem do banco. No modo design d o nome lblCodigo
ele, txtNome e txtTelefone aos textboxs. Deixe seu formulrio como o da imagem abaixo:

31

Agora precisamos sobrescrever os mtodos que, no formulrio base, foram declarados


como virtual,

como

o Salvar, Excluir, Localizar e Carregar Valores.

Para

isso,

aperte F7 no frmBase para ir a pgina de cdigos. O Visual Studio nos d uma grande ajuda
quando queremos sobrescrever mtodos j criados. Quando digitamos public override e damos
um espao, o VS j nos traz todos os mtodos que podemos utilizar do outro form, incluindo os
que criamos, como voc pode perceber na imagem a seguir: teste

Chame o mtodo Salvar e exclua o return base.Salvar(), pois no iremos us-lo. Aqui iremos
chamar nosso DataSet criado anteriormente, antes disso declare-o por meio do using. Como meu
mtodo espera um valor booleano, eu preciso declarar uma varivel do tipo bool e deix-la
como false, valor padro. Aps isso, instancio o PacienteTableAdapter e agora preciso chamar
meu enumeradorsStatus, se lembra dele? Mais aqui tem um problema: como ele foi declarado
como private, no consigo cham-lo aqui, j que ele privado a sua classe. Para isso, altere o
modificador dele para public. Agora sim, complete o mtodo abaixo, veja a imagem com os
comentrios do que foi feito:

32

Esta verificao para quando estiver inserindo. Mais, e quando o registro j foi inserido e quero
apenas atualiz-lo? Para isso, fao como na imagem a seguir (ainda dentro do meu mtodo
Salvar):

Como voc pode perceber, o mtodo Update vai dar erro porque ele espera ao menos 5
parmetros a serem preenchidos. Porque ele est pegando todos os campos de minha tabela e
est tentando comparar com os campos do meu mtodo. Para alterarmos isso, temos que ir ao
DataSet, clicarmos com o boto direito em Fill, GetData(), de meu PacienteTableAdapter, e
clicarmos em Configure, como mostra a imagem:

Agora

clique

em

Advanced

Options

desmarque

as

opes

Use optimistic

concurrency e Refresh the data table, como voc pode ver abaixo:

33

De OK, Next, Next e Finish. Volte ao mtodo Update e note que agora no ir mais dar erro. Veja
como deve ficar mtodo completo abaixo.

D um Build Solution (F6) apenas para ter certeza que sua soluo est sem erros e salve o
projeto.
Agora vamos sobrescrever o mtodo Excluir. Faa como o anterior:

Apenas chame o mtodo Localizar, j que no vamos implement-lo agora.


Agora, antes de chamar o mtodo que carrega os itens vamos imaginar o seguinte: j que em
meus mtodos eu preciso passar meu lblCodigo, referente ao cdigo do paciente, no seria
melhor se eu declarasse uma varivel que fosse a responsvel por este cdigo? Pensando assim,
vamos cri-la no nosso formulrio base. Abra o frmBase, v a pgina de cdigo e declare o
cdigo:

Desta forma, todos os meus cadastros herdaro essa varivel, que representa o cdigo
respectivo

de

cada

cliente

de

meu

consultrio.

Assim,

posso

us-la

nos

mtodos Localizar, Excluir e Salvar, substituindo pelo lblCodigo, j que no precisamos us-lo
mais. Por enquanto vamos deixar como est.
Agora chame o mtodo CarregaValores e dentro dele coloque o seguinte cdigo:

34

Aqui usamos aquela consulta que filtra pelo ID do Paciente, que criamos anteriormente em nosso
DataSet. Para isso, declarei o DataTable e o TableAdapter e fiz com que o DataTable retornasse
meu

TableAdapter

com

mtodo PesquisaID passando

como

parmetro

minha

varivel nCodGenerico, que ser preenchida pelo mtodo Localizar, lembrando que o Localizar
que ir chamar meu mtodoCarregaValores.
Aps isso eu verifico, se o DataTable retornou algum registro, preencho os controles de tela.
Lembrando que esse CarregaValores ser implementado em cada formulrio especfico.
Vamos criar agora um novo formulrio, que herdar do de Pesquisa. V na Solution, clique
em Add > New Item, em Categories escolha Windows Forms, escolha o template Inherited Form,
d o nome de PesquisaPaciente, clique em Add e escolha o frmPesquisaBase, j que nosso form
criado herdar dele.
Volte ao formulrio que estvamos, porque agora vamos implementar o mtodo Localizar. Digite
o seguinte cdigo:

O que fiz foi, instanciei o formulrio herdado de Paciente, verifiquei se o DialogResult desse form
foi igual a OK como configurado no formulrio base, ou seja, se o usurio escolheu algum registro
no formulrio e clicou em OK e, se sim, passamos a varivel bLocalizar o valor daquela
varivel sCdCodigo (que a responsvel pelo cdigo da pesquisa no formulrio base), diferente
de vazia. Aps isso, fazemos outra verificao. Se isso for verdade, ou seja, se a
varivel bLocalizar obtiver algum registro, minha varivel nCodGenerico receber o valor
35

de sCdCodigo. Acima fiz tambm um int.Parse para converter, pois a varivel sCdCodigo do
tipo string e a nCodGenerico, do tipo int.
Exemplo: o usurio est navegando entre os registros, decide escolher um e clica em OK. Neste
momento meu DialogResult setado para OK. Quando isso acontece, fao estas verificaes,
o bLocalizar recebe o valor de sCdCodigo, que na verdade o cdigo escolhido. Ele diferente
de vazio? , ento foi preenchido, o que significa que minha outra varivel, a nCodGenerico ir
receber o sCdCodigo. Simples n?!
A partir de agora, podemos utilizar esta varivel nCodGenerico em outros locais para substituir
meu cdigo. No mtodo CarregaValores j estamos usando ela. Vamos fazer o mesmo no mtodo
Excluir e no mtodo Salvar:

Nosso formulrio de Cadastro est implementado.


Finalizando nosso artigo, v ao Form1, d dois cliques no boto Paciente e altere o cdigo para
chamar nosso formulrio. Agora ser chamado nosso formulrio herdado. Faa como a imagem
abaixo nos mostra:

Salve seu projeto e compile para testar se tudo saiu OK.


Nesta parte iremos implementar o mtodo Pesquisar, do formulrio de Pesquisa, referente
ao Cadastro de Pacientes para que, assim, nosso cadastro esteja completo usando os conceitos
36

de

Herana

Visual

de

formulrios.

Iremos

comear

tambm

uma

simulao

do

padro MVC (Model View Controller) em nosso sistema. Confira:


No formulrio de Pesquisa, vamos fazer o seguinte: de acordo com o tipo de pesquisa que o
usurio escolher (por ID ou Descrio), iremos utilizar um dos mtodos criados anteriormente em
nosso DataSet.
Abra o formulrio frmPesquisaPaciente e sobrescreva o mtodo Pesquisar, como mostra a
seguir:

Aps isso, dentro do mtodo criado, tente acessar o campo de pesquisa, herdado do formulrio
base, que se chama txtPesquisa. Voc ver na imagem abaixo que no ser possvel o acesso
ao mesmo.

Isso acontece porque, por padro, o modificador de acesso dos controles do tipo privado
(private), precisamos ento acessar o formulrio base e alter-lo para pblico (public), como
mostra a imagem:

Faa o mesmo com os RadioButtons Cdigo e Descrio e aperte F6 para dar um Build Solution.
Toda vez que voc precisar acessar um controle herdado desta forma, preciso alterar o
modificador para public no formulrio base.

37

Agora volte ao formulrio de pesquisa e note que voc ter acesso ao textbox de pesquisa e aos
radiobuttons. Altere o nome de seu formulrio de pesquisa para Pesquisar Paciente e volte ao
cdigo.
Dentro do mtodo sobrescrito Pesquisar, faa o seguinte cdigo:

O que fiz acima foi uma verificao simples, Se o usurio selecionar o RadioButton Cdigo,
passo ao DataTable o mtodo PesquisaID, criado no DataSet anteriormente, para ser pesquisado
o ID que o usurio digitar no campo de pesquisa. Seno, ou seja, se o usurio selecionar o
RadioButton Descrio passo ao DataTable o mtodo PesquisaNome, e uso a porcentagem (%)
entre o campo de pesquisa, que significa que ele ir procurar uma parte do nome.
Se eu tiver no banco um nome Carlos, por exemplo e digitar no campo rlo, ele ir me retornar o
nome Carlos no ListView, pois com esse parmetro de porcentagem, da clusula Like, ele ir
procurar por partes referentes ao nome pesquisado. Como meu DataSet no aceita/entende o
parmetro %, preciso declar-lo em meu cdigo. Agora salve e compile sua aplicao. Clique em
Pacientes e dever aparecer a tela de Cadastro de Paciente. Clique em Novo, digite um nome e
um telefone qualquer e clique em Salvar.

Agora clique no boto Localizar para ir ao formulrio de Pesquisa:


38

Acima digitei uma parte do nome, ele j me retornou o nome completo e o ID. E abaixo me
mostrou quantos registros foram retornados com essa parte do nome. Se voc der dois cliques
em cima do nome, ele trar a tela de Cadastro com o Nome e o ID preenchido:

Como voc perceber na imagem acima, os botes de Salvar e de Localizar esto desabilitados,
precisamos alterar algumas configuraes para que os botes sejam habilitados. Para isso, v ao
formulrio Base, v ao mtodo HabilitaDesabilitaControles e perceba que no boto Localizar s
esta habilitado o Status Navegando, adicione tambm o Editando e o Inserindo. No boto Salvar,
est

habilitado

Status Navegando e Inserindo,

falha

minha,

correto

seriam

os

Status Editando e Inserindo. Arrume os botes como mostra a imagem a seguir:

Salve e compile seu projeto. Clique em Pacientes e no boto Localizar. Digite um nome qualquer
na caixa de busca ou a deixe em branco e tecle ENTER. Voc ver o resultado da pesquisa:

39

Clique em um dos resultados da pesquisa. Se quisermos com que, quando o usurio teclar
ESPAO sobre um dos resultados, o formulrio de pesquisa se feche e abra o respectivo registro,
podemos implementar isso fazendo o seguinte: Abra o formulrio de Pesquisa Base, clique em
cima do ListView, v a janela de Propriedades e, no evento KeyDown, d dois cliques e adicione
o seguinte cdigo:

PS: tentei fazer este mtodo com a tecla ENTER, mais por uma razo desconhecida, no
consegui fazer funcionar. Se algum descobrir o porque, por favor poste nos comentrios.
Agora escolha um registro qualquer, abra-o e clique em Excluir. Como voc pode perceber, a
excluso feita em poucos segundos. O interessante seria perguntarmos ao usurio se ele
realmente deseja excluir o registro, mantendo assim uma certa padronizao em formulrios.
Para isso, v ao formulrio Base, entre no boto Excluir, e altere o cdigo para que fique desta
forma:

40

Acima fiz apenas a pergunta ao usurio se deseja excluir o registro com o uso de MessageBox.
Se ele clicar em no, nada acontecer. Se ele disser sim, ele entrar no mtodo Excluir, que j foi
implementado anteriormente e o usurio ver um MessageBox avisando que o registro foi
excludo. Simples.
Salve o projeto, compile, clique para excluir um registro e veja as modificaes.
Vamos comear a partir de agora uma simulao do padro MVC (Model View Controller), onde
nosso DataSet ser o Model e os formulrios so o nosso View. Precisamos criar agora o
Controller, que sero as classes que faro a abstrao dos dados da Model e ir fazer a ponte
com a View, ou seja, com essas classes poderemos abstrair os dados do nosso DataSet e onde
faremos a implementao dos mtodos que os formulrios iro chamar.
Para mais informaes sobre o padro MVC, acesse os links abaixo:
http://pt.wikipedia.org/wiki/MVC
http://www.macoratti.net/vbn_mvc.htm
http://msdn.microsoft.com/pt-br/magazine/cc337884.aspx
http://www.linhadecodigo.com.br/Artigo.aspx?id=1602
http://imasters.uol.com.br/artigo/12139/asp/asp_net_mvc/
Comearemos criando a classe de acesso a dados, que ir implementar alguns mtodos e
criaremos as classes que herdaro estes mtodos.
Na Solution Explorer, clique em Add > Class e d o nome AcessoDados a sua classe.

Lembrando o conceito de Herana, esta classe ser nossa classe Base, onde a partir dela sero
criados outras classes que herdaro os mtodos provenientes dela. Aqui iremos ter os mtodos
para Salvar, para Excluir, Pesquisa por ID e Pesquisa por Nome, seguindo nossa lgica do
sistema.
41

No nome da sua classe acrescente um public antes, para que ela possa ser acessada pelas
classes herdadas e crie o mtodo virtual de Salvar, que ser sobrescrito depois.

Como voc pode perceber, o mtodo Salvar recebe um parmetro booleano, que ir indicar,
dependendo do status, se o registro est sendo inserido ou alterado. Como fiz nos outros
mtodos do tipo bool, inicializarei este mtodo com o valor false como retorno. Crie tambm um
mtodo virtual booleano com o nome Delete. Este mtodo no ter nenhum parmetro, j que
funo apenas de excluir um registro.

Agora vamos criar um mtodo do tipo DataTable para pesquisar por ID, que receber como
parmetro um valor do tipo int. Antes disso, preciso declarar o namespace System.Data, para
que possamos usar o tipo DataTable.

Aps isso, faa o seguinte mtodo:

Faa tambm um mtodo do tipo DataRow, que ir me retornar somente uma linha, para
pesquisar pelo ID, passando como parmetro um valor do tipo int, parecido com o mtodo
anterior. A diferena deste que ir me retornar um DataRow e no um DataTable.

Assim podemos fazer pesquisas que iro retornar somente uma linha e tambm pesquisas que
iro retornar diversas linhas. Desta forma tenho vrias formas de pesquisar em meu sistema.
Desta forma, posso declarar dois mtodos com o mesmo nome, s que com o retorno e
parmetro diferente (ou nesse caso, sem parmetro).

42

Finalizando, faa um mtodo do tipo DataTable para pesquisar por nome, que ter um parmetro
do tipo string, que receber o nome pesquisado.

Assim teremos mtodos para Salvar, Excluir, Pesquisar por ID e Pesquisar por Nome.
Nesta parte iremos criar as classes e os mtodos que herdaro da classe de acesso a dados.
Confiram:
Crie a classe AcessoDadosPaciente, que herdar da nossa classe de acesso a dados. Agora vou
mapear os campos da minha tabela como propriedades dessa minha classe herdada. Declare a
propriedade privada _nCodPaciente:

Para que ela se torne um campo, precisamos usar o Refactor do Visual Studio (ou voc pode
fazer na mo). Para isso clico com o boto direito em cima dessa propriedade privada, clico
em Refactor > Encapsulate Field e dou um nome diferente a ela (geralmente seria o nome quase
igual da propriedade privada apenas sem o underline), como mostra a imagem a seguir:

O que me resultar no campo abaixo:

Faa o mesmo com mais duas propriedades, sNomePaciente e sNumTelefone. O resultado final
ser esse:

43

Agora vamos implementar os mtodos criados anteriormente na classe de Acesso a Dados. Logo
abaixo chame o mtodo de Salvar (lembrando que usamos o override para sobrescrever os
mtodos

Antes

virtuais

de

fazer

de

mtodo

acesso

sobrescrito

de

dados):

Salvar,

declarei

o Consultas.dsConsultaTableAdapters. Aps isso, crio o mtodo Salvar, muito parecido com o que
foi feito em outras pginas do projeto, s que a diferena ser que agora a nossa classe
de Acesso a Dados que ir abstrair esse mtodo. Assim declaro minha varivel bSalvar, instancio
o TableAdapter, fao a comparao descrita na imagem acima: se estiver gravando no banco,
chamo o ta.Insert, passando os parmetros declarados em nossa classe, referentes ao nome do
paciente e ao numero do telefone. Uso no final o maior que 0 apenas para dizer que minha
varivel bSalvar ser gravada/atualizada somente se houver algum registro, ou seja, se for maior
que 0. Se no estiver gravando no banco, est atualizando, ento chamo ota.Update, fao a
mesma coisa, s que passo 3 parmetros: o nome do paciente, o nmero do telefone e o cdigo
do paciente.
Lembrando: preciso preencher essas propriedades antes de chamar esse mtodo de Insero
e/ou Atualizao.
44

Fazendo desta forma, meus formulrios no precisam acessar diretamente o TableAdapter para
obter os dados, j que minha classe de Acesso a Dados far isso.
Como teste, abra o formulrio Paciente Herdado e v ao mtodo Salvar. Vamos experimentar
usar o mtodo de nossa classe de Acesso a Dados. Para isso, comente o cdigo do boto
de Salvar do formulrio e faa o seguinte cdigo:

Comentei todo o cdigo que usvamos para Salvar e, apenas instanciando a classe de Acesso a
Dados, fiz o mesmo mtodo, preenchendo as propriedades e passando os parmetros. Alm de
economizar linhas de cdigo, uso o conceito de MVC, j que dessa forma meu formulrio no
precisa usar os mtodos de acesso a dados diretamente. Ele apenas chama a classe responsvel
por isso, no caso a de Acesso a Dados. Outro ponto importante a se destacar o fato de que,
quaisquer validaes que precisarmos fazer, s fazer nas classes de dados. Assim no
precisaremos se preocupar em ir, formulrio a formulrio, validando o que precisa, s fazemos
uma nica vez. Mais pra frente, quando formos implementar essa forma de trabalhar com MVC
nos outros mtodos, no precisaremos mais chamar o TableAdapter em nosso form como
chamamos atualmente:

Vamos agora sobrescrever os outros mtodos. Volte a classe de Acesso a Dados e, logo abaixo
do mtodo Salvar, chame o mtodo Delete e insira o seguinte cdigo (muito parecido com o
cdigo do mtodo Salvar):

45

Chame agora o mtodo PesquisaID (o que tem parmetro), que parecido com o mtodo Delete
(a diferena que nele usamos o parmetro nCodGenerico e precisamos instanciar o DataTable,
alm claro do TableAdapter) e insira o seguinte cdigo:

Chame o PesquisaID. Como este mtodo no possui parmetros, vamos chamar os atributos
declarados no incio de nossa classe, referentes as colunas de nossa tabela. Insira o seguinte
cdigo:

Como o mtodo do tipo DataRow, apenas retorno o DataTable PesquisaID, que fizemos
anteriormente, e passo o comando Rows[0], que indica que quero pegar o 1 ndice (ou 1 linha)
de meu DataRow.
Simples n? Agora vamos ao PesquisaNome, que praticamente igual ao PesquisaID (com
parmetro), s precisamos trocar o parmetro, que string, e o mtodo:

Pronto, os mtodos esto sobrescritos.


Temos situaes em que, precisamos passar todos os campos, outras em que precisamos passar
o nome e o telefone, outros em que preciso passar somente o cdigo, quando for Pesquisa, por
exemplo, etc. Para no ter o trabalho de sempre ter de preencher todas as propriedades,
devemos sobrescrever o construtor da minha classe, desta forma:
46

Desta forma, em branco, sem receber nenhum parmetro nem valor.


Agora, crio outros construtores, analisando aquelas situaes descritas acima, em que posso
passar apenas o cdigo, ou o nome e telefone, etc. Confira:

Assim no terei o trabalho de instanciar as classes, chamar as propriedades e preench-las, j


meu construtor servir pra isso.
Dessa forma, teremos 4 construtores: um que no ter parmetro algum, um que ter o cdigo do
paciente, para quando precisarmos fazer Pesquisas por ID, um que passo o cdigo, o nome e o
telefone, quando for atualizao, por exemplo, e um construtor que passarei somente o nome e o
telefone, quando for uma insero. Assim percebam que podemos customizar nossas classes de
acordo com nossas necessidades.
Os valores que so passados como parmetros, so repassados s propriedades criadas no
comeo do cdigo.
Vamos

ento

fazer

as

modificaes

necessrias

nos

outros

mtodos

de

nosso

formulrio Paciente Herdado, como fizemos com o mtodo Salvar acima.


Abra esse form, abra o mtodo Delete e faa o digite o seguinte cdigo:

Primeiramente, comente (ou exclua) o using acima, j que no iremos mais utilizar o DataSet
nessa pgina, pois nossa classe de Acesso a Dados que a responsvel por se conectar ao
banco. Agora instanciamos a classe, usamos o 2 construtor que criamos, que tem como
47

parmetro o cdigo, ento passamos o _nCodGenerico, que preenchido pelo Localizar e o


usaremos para Excluir o registro. Finalizando apenas retorno o mtodo Delete, criado na classe.
Em resumo, tenho uma produtividade no cdigo, pois o que antes gastvamos 4 linhas, hoje
gastamos apenas 2. Pode parecer pouco, mais imagina em um sistema grande, com milhares de
pginas e linhas de cdigo. Isso aumenta e muito a produtividade e a facilidade de dar
manuteno, caso ocorra algum erro.
O mtodo Localizar no iremos alterar neste form, j que precisamos alter-lo no form
de Pesquisa. V ao mtodo CarregaValores e insira o seguinte cdigo:

Aqui eu instancio minha classe, passo como parmetro o _nCodGenerico, da mesma forma que o
mtodo Excluir, instancio um DataRow(que retorna apenas uma linha), passo a ele a classe
instanciada chamando o mtodo PesquisaID, aquele mtodo sem parmetro, j que quero
apenas retornar uma linha. Seno passaria o outro mtodo, do tipo DataTable. Depois verifico, se
o DataRow for diferente de nulo, preencho os campos que desejo, usando as propriedades
declaradas na classe, atribudas aos valores do formulrio.
Abra agora o formulrio Pesquisa Paciente, v ao mtodo Pesquisar e insira o seguinte cdigo:

48

Perceba que nesse mtodo pouca coisa mudou. A diferena que antes meu DataTable recebia
um TableAdapter, que chamava os mtodos de Pesquisa. Agora no, quem faz isso
minha classe de Acesso a Dados.
Salve tudo e compile, vamos testar o projeto. Clique em Pacientes, Novo, digite um nome e um
telefone e clique em Salvar. Se o seu projeto est igual o meu, ento houve um erro!

Este erro aponta que meu lblCodigo est vazio ou em um formato incorreto. Porque ainda no
temos o cdigo do Paciente. Para isso, devemos fazer a seguinte alterao (lembrando que
estamos no mtodo Salvar, do formulrio Paciente Herdado):

Fao uma simples verificao, se o status for Editando, preciso preencher o cdigo do Paciente.
Se for insero, no h essa necessidade. Agora compile, grave um novo registro, clique em
Localizar, teste a busca, dever estar funcionando corretamente. Agora d dois cliques no
resultado da busca, exclua o registro e perceba que o cdigo no foi excludo.
49

Como no podemos simplesmente ir ao mtodo Excluir e apagar o label manualmente, j que


temos rtulos diferentes, temos que ir ao formulrio base, irmos ao mtodo LimpaControles,
dentro do foreach dos controles, fazermos um if no controle do tipo Label, e excluirmos somente
o lblCodigo, que o nome de nosso label (se o label de seu form tiver outro nome, altere-o no if).
Para isso, v ao formulrio Base e insira o seguinte cdigo:

Assim utilizamos facilmente o conceito de Herana, j que no precisamos ir toda vez no mtodo
Excluir, e sim apenas uma vez no mtodo LimpaControles.
Finalizando, deixo um desafio a vocs. Para que implementem o Cadastro de Mdicos, usando
esses conceitos de Herana Visual, abordados nos artigos anteriores, e principalmente os
conceitos de MVC.
Nesta parte iremos criar o Cadastro de Consultas, implementando os mtodos da classe de
Acesso a Dados para que o mesmo funcione, com a incluso de 2 novos mtodos. Acompanhem:
Como dito no fim do artigo anterior, no final deste, segue o Cadastro de Mdicos incluso no
cdigo-fonte, que ser disponibilizado ao fim deste artigo, seguindo o padro dos outros
cadastros.
Dito isto, vamos criar o Cadastro de Consultas. Ele ser um pouco diferente dos outros
Cadastros, pois ter, na classe de Acesso a Dados 2 novos mtodos, o que ir Pesquisar pelo
nome do Paciente e a Pesquisa pelo nome d Mdico
Primeira modificao a ser feita em nosso DataSet, j que devemos implementar os tipos de
consultas que iremos fazer, pelo cdigo da consulta, pelo nome do paciente e/ou pelo nome do
mdico.

50

Abra seu DataSet (no meu caso, o nome dsConsulta) e clique com o boto direito
no ConsultaTableAdapter, e clique em Add Query, para criarmos os mtodos da mesma forma
como fizemos anteriormente. Este 1 mtodo ser o de Pesquisa por ID da Consulta.

Como feito anteriormente, clique em Use SQL Statements e SELECT which returns rows, clique
em Next para aparecer esta tela:

Devemos alterar esta instruo SQL, j que queremos retornar o ID da Consulta, Nome do
Medico, Nome do Paciente, Data da Consulta e Hora Inicial. Iremos tambm fazer um INNER
JOIN (ligao entre duas ou mais tabelas) com as tabelas Medico e Paciente. Para fins didticos
(e seguindo a videoaula) vamos usar o Query Builder. Clique nele e, na tela que aparece, clique
com o boto direito na parte branca ao lado da tabela Consulta e clique em Add Table, adicione
as tabelas Medico e Paciente, selecione os seguintes campos e execute a instruo:

51

Nossa instruo SQL ficar da seguinte forma:

S que ainda no est pronta. Vamos usar dois filtros, para retornarmos as consultas
parametrizadas pelo ID e pesquisarmos as consultas apenas que estiverem ativas. Altere sua
instruo para que fique desta forma:

Clique em Next e na prxima tela, deixe selecionado a 1 opo, Fill a DataTable, d o nome
de PesquisaID para ele, clique em Next e em Finish. Dever aparecer esta mensagem:

Que apenas indica que a instruo SQL usada nos retorna dados diferentes das outras consultas,
sem problemas.
Nosso campo Ativo est com o valor nulo (NULL), se o deixarmos assim, nossa query recm
criada no ir funcionar. Abra o SQL Server e confirme:
52

Para que funcione, devemos alterar este valor do campo Ativo. No SQL Server execute a seguinte
instruo:

Agora sim, nossa query ir funcionar, j que nosso campo Ativo est com o valor 1 (True). Para
testar, clique com o boto direito em cima da query e clique em Preview Data. Na janela que
surge, coloque o valor parametrizado de nossa consulta, que no caso referente ao
campo IdConsulta e clique em Preview:

Nosso prximo mtodo ser pelo Nome do Paciente. Faa o mesmo procedimento que o mtodo
anterior, s altere a instruo SQL para a de baixo:

Clique em Next, selecione apenas a 1 opo, d o nome de PesquisaNomePaciente e clique


em Finish. Faa o mesmo para o prximo mtodo, alterando a instruo SQL para nos retornar o
nome do mdico e dando o nome de PesquisaNomeMedico:

53

Assim nossa tabela Consulta ter 3 pesquisas diferentes:

Agora vamos a classe AcessoDados para criarmos a classe de AcessoDadosConsulta que, assim
como as outras, ir herdar de AcessoDados e ter os mesmos mtodos da classe base e mais os
2 mtodos que implementamos a pouco:

Como

voc

pode

perceber,

implementei

os

mtodos PesquisaNomePaciente e PesquisaNomeMedico, o resto so os mtodos sobrescritos


de minha classe base AcessoDados. No implementei estes 2 ltimos mtodos da classe base,
pois os mtodos da classe base so genricos a todas as outras classes. Estes ltimos so
especficos para esta classe.
Nesta parte iremos criar os cdigos referentes aos mtodos criados anteriormente da
classe de Consulta. Aps isso, criaremos tambm um novo formulrio, que ser o de Pesquisa
das Consultas. Acompanhem:
Abra o DataSet de Consulta, para que modifiquemos o mtodo Fill, do ConsultaTableAdapter.
Vamos alter-lo para que sejam retornadas apenas as consultas que estiverem ativas. Para isso,
clique com o boto direito em cima do mtodo Fill do ConsultaTableAdapter e clique
em Configure. Altere a instruo SQL que aparece para a seguinte:

54

Nessa mesma tela, clique no boto Advanced Options e, na tela que aparece, desmarque as
duas ltimas opes, como mostra a imagem a seguir:

Desmarcando essas opes, no iremos ter vrios parmetros em nosso mtodo, dessa forma
estaremos evitando o uso de concorrncia. D OK, clique em Next, Next na prxima tela tambm
e Finish. Assim iremos retornar somente as consultas que estiverem ativas.
Agora vamos criar em nossa classe de Acesso a Dados o mtodo Pesquisar, que ser
responsvel por realizar todas as pesquisas. Ento crie o mtodo, como mostra abaixo:
PS: A partir de agora irei colocar em meus artigos desta srie (como j fao com artigos
de ASP.NET e SQL Server) o cdigo em si e no mais prints do cdigo, apenas com o intuito de
no poluir com muitas imagens os artigos.
public DataTable Pesquisar()
{
try
{
//instancio o TableAdapter e o DataTable
ConsultaTableAdapter ta = new ConsultaTableAdapter();
dsConsulta.ConsultaDataTable dt = new dsConsulta.ConsultaDataTable();
//uso o mtodo Fill do TableAdapter, passando como parmetro o DataTable
ta.Fill(dt);
//retorno o DataTable preenchido
return dt;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

A implementao dos outros mtodos parecida com a das outras classes de Acesso a Dados.
Vamos criar as propriedades relativas aos campos do banco nesta classe como feito
anteriormente, mais desta vez faremos de uma forma otimizada. Ao invs de criarmos as
propriedades privadas e pblicas, podemos criar a pblica e j declarar direto o get e set,
poupando assim cdigo. Veja:
55

public
public
public
public
public
public
public
public

int nCodConsulta { get; set; }


int nCodMedico { get; set; }
int nCodPaciente { get; set; }
DateTime dDtConsulta { get; set; }
DateTime dHrInicio { get; set; }
DateTime dHrFim { get; set; }
string sObservacao { get; set; }
bool bAtivo { get; set; }

Lembrando que esse recurso est disponvel a partir da verso 2008 do Visual Studio.
Vamos implementar o cdigo do mtodo Salvar, bem parecido com o mtodo das outras classes:
public override bool Salvar(bool bInsert)
{
try
{
//instancio o TableAdapter
ConsultaTableAdapter ta = new ConsultaTableAdapter();
//crio uma varivel auxiliar, que ser retornada preenchida no fim do mtodo
bool bSalvar = false;
//verifico, se estiver inserindo, minha varivel bSalvar recebe o mtodo Insert
//do TableAdapter, passando como parmetro as propriedades criadas no comeo da
classe
if (bInsert)
{
bSalvar = (ta.Insert(nCodMedico, nCodPaciente, dDtConsulta,
dHrInicio, dHrFim, sObservacoes, true) > 0);
}
//seno, uso o mtodo Update e passo a propriedade bAtivo como parmetro do
mtodo
else
{
bSalvar = (ta.Update(nCodMedico, nCodPaciente, dDtConsulta, dHrInicio,
dHrFim, sObservacoes, bAtivo, nCodConsulta) > 0);
}
return bSalvar;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Neste cdigo, se o mtodo for Insert, passo como parmetro as propriedades criadas
anteriormente e o valor true, como padro, ou seja, sempre que for gravar, ir gravar a consulta
com o status Ativo. J no mtodo Update, preciso passar a propriedade bAtivo, j que posso ter a
situao do usurio estar querendo alterar o status de Ativo para Inativo, por isso devo pass-la.
O mtodo Delete bem simples, nem preciso usar a varivel auxiliar. Veja:
public override bool Delete()
{
try
{
//instancio o TableAdapter
ConsultaTableAdapter ta = new ConsultaTableAdapter();
//retorno o mtodo Delete passando a propriedade nCodConsulta como parmetro
return (ta.Delete(nCodConsulta) > 0);
}
catch (Exception ex)

56

{
throw new Exception(ex.Message.ToString());
}
}

Os prximos dois mtodos PesquisaID sero iguais aos mtodos das classes anteriores. Confira:
public override DataTable PesquisaID(int nCodGenerico)
{
try
{
//instancio o DataTable e o TableAdapter
dsConsulta.ConsultaDataTable dt = new dsConsulta.ConsultaDataTable();
ConsultaTableAdapter ta = new ConsultaTableAdapter();
//uso

mtodo

PesquisaID,

passando

como

parmetro

dt

varivel

nCodGenerico
ta.PesquisaID(dt, nCodGenerico);
//retorno o DataTable preenchido
return dt;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}
public override DataRow PesquisaID()
{
try
{
//retorno apenas a primeira linha de minha consulta
return this.PesquisaID(nCodConsulta).Rows[0];
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Os mtodos PesquisaNomePaciente e PesquisaNomeMedico sero tambm praticamente iguais


em sua estrutura, s mudara que usarei os caracteres coringas (%) como filtro de pesquisa, ou
seja, quando o usurio digitar por exemplo ton, ser pesquisado todos os nomes que contenham
essas letras.
public DataTable PesquisaNomePaciente(string sDsNomePaciente)
{
try
{
//instancio o DataTable e o TableAdapter

57

dsConsulta.ConsultaDataTable dt = new dsConsulta.ConsultaDataTable();


ConsultaTableAdapter ta = new ConsultaTableAdapter();
//uso o mtodo PesquisaNomePaciente, passando como parmetro o dt
//e os caracteres coringas, concatenados com a varivel sDsNomePaciente
ta.PesquisaNomePaciente(dt, "%" + sDsNomePaciente + "%");
//retorno o DataTable preenchido
return dt;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}
public DataTable PesquisaNomeMedico(string sDsNomeMedico)
{
try
{
//instancio o DataTable e o TableAdapter
dsConsulta.ConsultaDataTable dt = new dsConsulta.ConsultaDataTable();
ConsultaTableAdapter ta = new ConsultaTableAdapter();
//uso o mtodo PesquisaNomePaciente, passando como parmetro o dt
//e os caracteres coringas, concatenados com a varivel sDsNomeMedico
ta.PesquisaNomeMedico(dt, "%" + sDsNomeMedico + "%");
//retorno o DataTable preenchido
return dt;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Pronto, nossa classe est implementada. Agora vamos criar nosso formulrio de Pesquisa que,
diferente dos outros, ter trs tipos de pesquisas: pelo Cdigo, pelo Nome do Mdico e
pelo Nome do Paciente.
Ento,

clique

em Add > Windows Forms,

na

Solution

Explorer,

selecione

template InheritedForm, d o nome de frmPesquisa a ele e clique em OK. Na tela que surge
perguntando de qual form voc ir herdar, escolha o frmBase.
Como j disse, esse formulrio ter trs tipos de pesquisas, s que como ele herdado do
formulrio base, nos trouxe apenas os dois padres, por Cdigo e Descrio.
Precisamos ento ir ao frmBase e alterar o modificador de acesso de alguns controles
para public (repare no frmPesquisa que esto como private com um cadeado, no possvel

58

mov-los

ou

redimension-los).

Ento,

ao frmBase,

altere

propriedade Modifiers do GroupBox, GridView e dos dois Buttons.


Aps

fazer

isso,

um Build

Solution (F6).

Agora

ao frmPesquisa,

adicione

um RadioButton com o text Nome do Mdico para que fique dessa forma:

Em nosso form precisamos sobrescrever o mtodo Pesquisar, criado no formulrio base. Para
isso, faa o seguinte:
public override void Pesquisar()
{
try
{
//instancio a Classe e o DataTable
AcessoDadosConsulta acesso = new AcessoDadosConsulta();
DataTable dt = new DataTable();
//verifico qual RadioButton est checado, dependendo de qual for, chamo o mtodo
adequado
if (rbtCodigo.Checked)
{
dt = acesso.PesquisaID(int.Parse(txtPesquisa.Text));
}
else if (rbtDescricao.Checked)
{
dt = acesso.PesquisaNomePaciente("%" + txtPesquisa.Text + "%");
}
else if (rbtNomeMedico.Checked)
{
dt = acesso.PesquisaNomeMedico("%" + txtPesquisa.Text + "%");
}
//crio um novo mtodo para carregar os itens no ListView
Carregar(dt);
}
catch (Exception ex)

59

{
throw new Exception(ex.Message.ToString());
}
}

Como voc pode ver acima, a diferena desse mtodo com o do form frmPesquisaPaciente, por
exemplo, que no iremos usar o mtodo CarregarItens, j que o mesmo usa apenas as 2
colunas do ListView e no nosso form usaremos mais do que isso. Ento vamos criar o mtodo
que foi chamado acima (que ter como diferena o nmero de colunas apenas):
private void Carregar(DataTable dt)
{
try
{
//limpo os registros do ListView
lstPesquisa.Items.Clear();
//carrego os dados no ListView
foreach (DataRow dr in dt.Rows)
{
//para cada linha de meu DataTable, insiro uma linha no ListView
//instancio o ListViewItem, adiciono os itens e subitens, referentes
//aos campos que estou pesquisando em meu ListView
ListViewItem item = new ListViewItem();
item.Text = dr["IDCONSULTA"].ToString();
item.SubItems.Add(dr["NOMEPACIENTE"].ToString());
item.SubItems.Add(dr["NOMEMEDICO"].ToString());
item.SubItems.Add(dr["DATACONSULTA"].ToString());
item.SubItems.Add(dr["HORAINICIO"].ToString());
//aqui adiciono a varavel instanciada item
//carregada com o item e subitem ao ListView
lstPesquisa.Items.Add(item);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Ok, agora temos que adicionar estas colunas a mais em nosso ListView. Antes disso, precisamos
alterar o modificador de acesso das colunas que j existem para public. Ento v
ao frmPesquisaBase e abra na SmartTag do ListView a opo Edit Columns.
Nela, altere a propriedade das colunas para public, como mostra a imagem:

60

D OK, um Build Solution para atualizar o projeto e volte ao frmPesquisa.


Nele adicione trs colunas, para que o ListView fique como na imagem a seguir:

Vamos testar o form. Antes de rod-lo, abra o Form1.cs (o form principal) e altere o boto que
chama as Consultas:

private void toolStripButton3_Click(object sender, EventArgs e)


{
//frmConsulta consulta = new frmConsulta();
//consulta.ShowDialog();
frmPesquisa pesquisa = new frmPesquisa();
pesquisa.ShowDialog();
}

Salve e compile o projeto. Clique no boto Consultas para ver o resultado:

61

Nesta parte iremos fazer algumas alteraes em nosso DataSet para que nosso formulrio
de Pesquisas, criado anteriormente funcione corretamente e comear a criao do Cadastro de
Consultas implementando os mtodos necessrios para que o mesmo funcione. Acompanhem:
Como dito anteriormente, antes de criarmos o Cadastro de Consultas, devemos realizar algumas
alteraes em nosso DataSet para que nosso formulrio de Pesquisas criado na parte anterior
funcione.
Se ao executarmos o formulrio de Pesquisas e tentarmos realizar uma pesquisa, ser disparado
o seguinte erro:

Este erro acontece porque em nossos mtodos de Pesquisa do TableAdapter de Consulta do


nosso DataSet estamos retornando mais campos do que temos em nosso TableAdapter:

Como voc pode perceber pela imagem acima, estamos tentando retornar o Nome do Mdico e
o Nome do Paciente que esto em outras tabelas, por isso est dando este erro de constraint. Se
deixarmos assim, podem dar outros erros, como na hora da insero de um novo registro
neste TableAdapter, j que os valores Nome do Mdico e Nome do Paciente no pertencem a
este TableAdapter.
Para resolvermos isso, vamos criar um TableAdapter exclusivo para as Pesquisas.
62

Clique com o boto direito em cima do mtodo PesquisaID, do TableAdapter de Consultas e


clique em Configure. Copie a query que aparece, pois vamos us-la no TableAdapter que iremos
criar.
Crie o TableAdapter usando a mesma string de conexo que os outros. Cole a query que voc
copiou, clique em Advanced Options e desmarque as trs opes, j que nossa query ser
apenas para consulta:

Na prxima tela desmarque a opo Return a DataTable e na opo Fill a DataTable d o nome
de PesquisaID,

clique

nosso TableAdapter.

em Next e Finish.

Ir

Faa

aparecer
o

os

campos

mesmo

de

consulta
com

mtodos PesquisaNomeMedico e PesquisaNomePaciente do TableAdapter de Consultas,

em
os
ou

seja, copie a query deles, crie mtodos em nosso novo TableAdapter e cole essas querys. O
resultado final de nosso TableAdapter ser este:

Apenas clique com o boto direito em cima da coluna IDCONSULTA e clique em Delete Key para
excluirmos a chave primria, j que, como j dissemos, usaremos este TableAdapter apenas para
pesquisas.
Podemos concluir que, para cadastros o uso do TableAdapter excelente (neste tipo de exemplo
simples), j para consultas devemos analisar bem a situao. Se fizermos uma consulta que
contenha mais colunas que o nosso TableAdapter (como nesse exemplo), devemos criar
outro TableAdapter, especfico para isso.
Exclua os mtodos que copiamos, do TableAdapter de Consultas e d um Build Solution (F6) em
sua aplicao, teremos alguns erros na classe de Acesso a Dados, pois devemos alterar
nosso DataTable e o TableAdapter, de Consultas para Pesquisas.
63

Voltando ao DataSet, vamos adicionar uma nova query no TableAdapter Consultas, que nos
retornar todas as pesquisas. A diferena que esta query ir nos retornar as consultas que
estiverem ativas, ou seja, com o status Ativo = 1.

Agora volte a classe de Acesso a Dados e altere o mtodo Pesquisar para o seguinte:
public DataTable Pesquisar()
{
try
{
//instancio o TableAdapter e o DataTable
dsConsulta.PesquisasDataTable dt = new dsConsulta.PesquisasDataTable();
PesquisasTableAdapter ta = new PesquisasTableAdapter();
//uso o mtodo Fill do TableAdapter, passando como parmetro o DataTable
ta.Pesquisar(dt);
//retorno o DataTable preenchido
return dt;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Somente trocamos o DataTable e TableAdapter, como feito nos outros mtodos, e chamamos o
mtodo Pesquisar, que acabamos de criar. Compile a aplicao, clique em Consultas, teste o
formulrio e voc ver que agora est funcionando corretamente:

64

Para deixarmos 100% nosso formulrio, vamos formatar nossos campos de Data e Hora usando
um recurso importante de formatao do .NET, que o string.Format
V

ao frmPesquisa.cs e,

campo DATACONSULTA exiba

no

mtodo Carregar,
somente

use

data

o string.Format para
no

que

formato dd/MM/yyyy e

o
o

campo HORAINICIO exiba a hora no formato HH:mm, como o cdigo abaixo nos mostra:
item.SubItems.Add(string.Format("{0:dd/MM/yyyy}", dr["DATACONSULTA"]));
item.SubItems.Add(string.Format("{0:HH:mm}", dr["HORAINICIO"]));
Perceba que tirei o ToString() do final dos campos, j que o string.Format espera um objeto (onde
est meu dr[DATACONSULTA] por exemplo) e se eu passar o ToString() ele reconhece como
um simples texto e no aplica a formatao correta no campo.
Salve e compile para ver o resultado:

Pronto, formulrio finalizado. Agora sim vamos criar o Cadastro de Consultas.


65

Podemos

perceber

em

nosso TableAdapter de Pesquisas que

temos o Nome do Medico e

o Nome do Paciente, ou seja, nossa tabela de Consultas tem chaves estrangeiras, referente as
tabelas Medico e Paciente. Em nosso form no podemos colocar textboxes para o usurio digitar
o nome do Mdico e do Paciente, muito menos os respectivos IDs deles, j que, no temos a
garantia de que o usurio ir digitar o nome ou ID correto.
Dessa forma como podemos ter a certeza que o cadastro de uma consulta ser vinculada a
um Mdico e a um Paciente? Por meio de consultas auxiliares, ou seja, a partir de nosso form
de Cadastro de Consultas o usurio ir escolher o nome ou cdigo do Mdico e far o mesmo
com o Paciente. Assim iremos reaproveitar as telas de Pesquisa que j temos, eliminando o
trabalho de criar duas telas novas com novos controles e tudo mais.
Com essa idia em mente, vamos criar um novo form. V na Solution Explorer (CTRL + W + S),
clique com o boto direito na soluo e clique em Add > New Item. Escolha a categoria Windows
Form, o template Inherited Form (que indica que nosso form ser herdado de outro) e d o nome
a ele de frmConsultaHerdado. Na tela que aparece para selecionar o formulrio que herdaremos,
escolha ofrmBase e clique em OK.
Adicione alguns labels, textboxes e buttons, para que seu form fique como o da imagem a seguir:

Os IDs e propriedades dos controles so:


Labels lblNomePaciente, lblNomeMedico, lblDtConsulta, lblHrInicio, lblHrFim e lblObservacoes.
Textboxes txtNomePaciente, txtNomeMedico, estes dois com a propriedade ReadOnly = True
(que indica que nossos textboxes sero somente leitura) e com texto em negrito, e
txtObservacoes, este ltimo com a propriedade Multiline para True.
Datetimepicker dtConsulta, dtHrInicio e dtHrFim. Altere tambm a propriedade Custom
Format do dtConsulta para dd/MM/yyyy e altere a propriedade Format para Custom. Faa o
mesmo com os outros datetimepicker, colocando no Custom Format o valor HH:mm.

66

Buttons btnConsultarPaciente e btnConsultarMedico. Por enquanto deixaremos com este


texto btn, depois alteraremos para uma imagem para demonstrar ao usurio que esses botes
serviro para pesquisar os pacientes e mdicos.
No formulrio base temos uma varivel pblica, que visvel em todo o formulrio que herda
deste form, responsvel por armazenar um cdigo genrico. Assim, em nossos cadastros
de Paciente e de Mdico quando fazemos a gravao dos dados usamos esta varivel para
receber o ID da gravao. Em nosso cadastro de consulta, temos que fazer o mesmo, criar duas
variveis que sero responsveis por armazenar os cdigos de Paciente e de Mdico.
Ela ser preenchida no momento em que clicarmos nos botes que criamos, pesquisarmos pelo
Paciente e/ou Mdico, o selecionarmos na pesquisa, clicarmos em OK e voltarmos ao nosso
form. Nesse momento nossas variveis recebero os cdigos respectivos de cada formulrio.
Por enquanto v pgina de cdigos de nosso form e declare as variveis responsveis por
receber estes cdigos:
public int _nCodPaciente;
public int _nCodMedico;

Agora volte ao formulrio e d dois cliques nos botes para chamar o evento Click dos mesmos.
Neles,

faa

seguinte

cdigo

para

chamar

os

formulrios

responsveis

por

pesquisar Paciente e Mdico, respectivamente:


private void btnConsultarPaciente_Click(object sender, EventArgs e)
{
frmPesquisaPaciente frmPesquisaPaciente = new frmPesquisaPaciente();
if (frmPesquisaPaciente.ShowDialog() == DialogResult.OK)
{
if (frmPesquisaPaciente.sCdCodigo != string.Empty)
{
_nCodPaciente = int.Parse(frmPesquisaPaciente.sCdCodigo);
}
}
}
private void btnConsultarMedico_Click(object sender, EventArgs e)
{
frmPesquisaMedico frmPesquisaMedico = new frmPesquisaMedico();
if (frmPesquisaMedico.ShowDialog() == DialogResult.OK)
{
if (frmPesquisaMedico.sCdCodigo != string.Empty)
{
_nCodMedico = int.Parse(frmPesquisaMedico.sCdCodigo);
}
}

67

Percebam que estes cdigos so iguais aos do boto Localizar dos forms de cadastro de
Paciente e Mdico. Assim nossas variveis sero preenchidas com os cdigos vindos do registro
pesquisado pelo usurio nos forms.
Dessa forma estamos reaproveitando cdigo e melhorando o desempenho de nossa aplicao,
pois no precisamos criar novas telas para fazer isso.
Vamos testar nosso form agora. V ao formulrio principal de Consultas, d dois cliques no boto
Consultas e altere o cdigo do mesmo para o de baixo:
private void toolStripButton3_Click(object sender, EventArgs e)
{
frmConsultaHerdado frmConsulta = new frmConsultaHerdado();
frmConsulta.ShowDialog();
}

Salve e compile. Clique no boto Consultas para que nosso form se abra. Agora clique em Novo e
clique em um dos botes que criamos para ver que ser aberto o form de Pesquisa.
Selecione um registro e clique em OK, voltaremos ao nosso form, mais nosso textbox no ser
preenchido com o registro selecionado, pois falta implementarmos o mtodo que pesquisar
o Mdico e o Paciente. Seguindo essa linha de reaproveitamento de cdigo, usaremos os
mtodos j criados em nossa classe de Acesso a Dados.
Ol pessoal, nesta parte iremos continuar as alteraes em nosso Cadastro de Consultas,
feitas,

realizando

alteraes

no

formulrio

criando

os

mtodos Salvar, Excluir, Localizar e Carrega Valores.


Acompanhem: Voltando ao nosso frmConsultaHerdado, temos em nossos botes j
implementados a consulta de Mdico e Paciente. Vamos adicionar uma imagem a eles.
Para isso, abra a ToolBox, arraste o controle ImageList para o formulrio e clique na
opo Choose images, como voc pode ver abaixo:

A imagem escolhida estar disponvel para download ao final do artigo, juntamente com o
projeto.

Clique

em Add,

escolha a

imagem,

clique

em Abrir e

d OK.

Altere

propriedade TransparentColor, do ImageList, para Magenta, a fim de deixar a imagem


transparente.
68

Agora v nas propriedades dos botes do form, limpe a propriedade Text, selecione na
propriedade ImageList o controle que arrastamos pro form, e na propriedade ImageKey selecione
a imagem que adicionamos ao ImageList, como a imagem abaixo ilustra:

No artigo anterior, no estvamos retornando o nome do Paciente nem do Mdico em nosso


formulrio, apenas armazenamos os IDs deles nas variveis _nCodPaciente e _nCodMedico.
Para resolvermos isso, podemos fazer de dois modos, iremos ver ambos a seguir:
Modo

Aqui

iremos

criar

um

mtodo

nas

classes AcessoDadosPaciente e AcessoDadosMedico, dentro da classe pai de Acesso a Dados,


que ir fazer duas consultas no banco, uma que ir retornar o nome do Paciente e outra que
retornar o nome do Mdico. Para isso, v s respectivas classes e faa o seguinte mtodo:
public string PesquisaNome(int nCodGenerico)
{
//Crio um DataTable, que recebe meu mtodo PesquisaID
DataTable dt = PesquisaID(nCodGenerico);
//Verifico se meu DataTable contm linhas, se tiver retorno o mtodo PesquisaID,
//Exibindo a primeira linha e a coluna com o nome do Paciente, convertido para
string.
//Se no tiver linhas retorno uma string vazia.
if (dt.Rows.Count > 0)
{
return PesquisaID(nCodGenerico).Rows[0]["NOMEPACIENTE"].ToString();
}
else
{
return string.Empty;
}
}

Seguindo esta lgica, crie o mesmo mtodo para a classe AcessoDadosMedico.


Agora volte ao frmConsultaHerdado, v ao mtodo referente aos eventos click dos botes
de Paciente e Mdico (coloquei os cdigos dentro de mtodos para facilitar o tratamento de erros
e s fiz a chamada ao mtodo nos botes) e altere a codificao deles para a seguinte:
private void ConsultarPaciente()

69

{
AcessoDadosPaciente objPaciente = new AcessoDadosPaciente();
frmPesquisaPaciente frmPesquisaPaciente = new frmPesquisaPaciente();
try
{
if (frmPesquisaPaciente.ShowDialog() == DialogResult.OK)
{
if (frmPesquisaPaciente.sCdCodigo != string.Empty)
{
_nCodPaciente = int.Parse(frmPesquisaPaciente.sCdCodigo);
//Meu

txtNomePaciente

recebe

objPaciente

chamando

mtodo

PesquisaNome,
//passando como parmetro a varivel _nCodPaciente
txtNomePaciente.Text = objPaciente.PesquisaNome(_nCodPaciente);
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Perceba

que

agora

estou

usando

mtodo

da

classe

de

Acesso

Dados,

que implementei anteriormente.


Seguindo esta lgica, faa o mesmo com o mtodo ConsultarMedico.
Mtodos implementados, aperte F5 para compilar o projeto, clique nesses botes para consultar
o Mdico e o Paciente e veja que agora os campos texto so preenchidos:

Perceba que desta forma estamos fazendo consultas ao banco duas vezes, uma para
pesquisarmos o nome e, dentro dela, outra para retornarmos o nome do Mdico ou Paciente. Veja
da outra forma como isso diferente:
Modo 2 Aqui, ao invs de fazer duas consultas ao banco, iremos trabalhar com a passagem
de variveis entre formulrios.
70

Usaremos o frmPesquisaBase, que j contm uma varivel auxiliar (com o nome sCdCodigo)
que recebe o cdigo da consulta quando pesquisado por um Mdico ou Paciente.
Se voc notar a codificao dos mtodos para Consultar Mdico e Consultar Paciente perceber
que est varivel j usada em nosso formulrio para consultarmos o ID do usurio pesquisado:
_nCodPaciente = int.Parse(frmPesquisaPaciente.sCdCodigo);

Ento, s precisamos criar outra varivel no frmPesquisaBase que ir receber o nome do usurio
pesquisado. Lembrando que este exemplo serve para este caso, em que temos apenas duas
colunas em nosso ListView.
Dito tudo isto, abra o frmPesquisaBase e declare uma varivel do tipo string que receber o
nome pesquisado em nossa consulta (perceba que ela declarada logo abaixo da
varivel sCdCodigo):
//Declaramos as variveis pblicas do tipo string
public string sCdCodigo;
public string sDsNome;
Aproveite tambm para inicializar esta varivel com o valor vazio, no construtor da classe:
public frmPesquisaBase()
{
InitializeComponent();
//Inicializamos as variveis com valor vazio
sCdCodigo = string.Empty;
sDsNome = string.Empty;
}
Dentro do evento Click do boto OK, altere o cdigo para o seguinte:
//fao a verificao se a varivel sCdCodigo est vazia
if (sCdCodigo == string.Empty)
{
//se estiver vazia e o foco estiver no ListView preencho as variveis
if (lstPesquisa.Focused)
{
sCdCodigo = lstPesquisa.SelectedItems[0].Text;
sDsNome = lstPesquisa.SelectedItems[0].SubItems[1].Text;
}
}

Perceba no cdigo acima que estou passando a varivel recm-criada para ser preenchida
pelo ListView.

Insira

esta

linha

tambm

no

evento DoubleClick e

tambm

nos

eventos KeyDown e SelectedIndexChanged, do ListView.


Assim nossa varivel sDsNome ser preenchida sempre que consultarmos um usurio neste
formulrio. E ela que passaremos ao frmCadastroHerdado.
Volte novamente a este formulrio e, no mtodo ConsultarPaciente, altere-o para o seguinte:
71

private void ConsultarPaciente()


{
frmPesquisaPaciente frmPesquisaPaciente = new frmPesquisaPaciente();
try
{
if (frmPesquisaPaciente.ShowDialog() == DialogResult.OK)
{
if (frmPesquisaPaciente.sCdCodigo != string.Empty)
{
_nCodPaciente = int.Parse(frmPesquisaPaciente.sCdCodigo);
txtNomePaciente.Text = frmPesquisaPaciente.sDsNome;
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Veja que assim, no precisaremos usar a classe de Acesso a Dados e, consequentemente, no


faremos duas consultas ao banco, ganhando assim em performance. S fazer a mesma alterao
no mtodo ConsultarMedico.
Aperte F5 e faa uma consulta para ver se est tudo OK:

V classe de Acesso a Dados, e na classe AcessoDadosConsulta, crie o seguinte construtor:


public AcessoDadosConsulta(int nCodConsulta)
{
this.nCodConsulta = nCodConsulta;
}

Com este construtor criado no teremos problemas ao retornar registros de consultas em nosso
formulrio, quando criarmos o mtodo CarregaValores.
Seguindo

as aulas que

originaram

este

artigo,

vamos

agora

criar

os

mtodos Salvar, Excluir, Localizar e Carrega Valores, bem parecidos com os mtodos de outros
formulrios. Veja a codificao de cada um a seguir:
72

Salvar
public override bool Salvar()
{
try
{
bool bSalvar = false;
//Instancio a classe de Acesso a Dados
AcessoDadosConsulta objConsulta = new AcessoDadosConsulta(_nCodGenerico);
//Se estiver editando, minha varivel nCodConsulta, da classe de Acesso a Dados
recebe o _nCodGenerico
if (sStatus == StatusCadastro.scEditando)
{
objConsulta.nCodConsulta = _nCodGenerico;
}
//Preencho os valores do form
objConsulta.nCodMedico = _nCodMedico;
objConsulta.nCodPaciente = _nCodPaciente;
objConsulta.dDtConsulta = dtConsulta.Value;
objConsulta.dHrInicio = DateTime.Parse(dtHrInicio.Value.ToShortTimeString());
objConsulta.dHrFim = DateTime.Parse(dtHrFim.Value.ToShortTimeString());
objConsulta.sObservacoes = txtObservacoes.Text;
bSalvar = (objConsulta.Salvar(sStatus == StatusCadastro.scInserindo));
return bSalvar;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Excluir

public override bool Excluir()


{
try
{
AcessoDadosConsulta objConsulta = new AcessoDadosConsulta();
return objConsulta.Delete();
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Localizar
public override bool Localizar()
{
try

73

{
bool bLocalizar = false;
frmPesquisa frmPesquisa = new frmPesquisa();
//fao abaixo uma verificao, se o usurio clicar em OK
//minha varivel bLocalizar recebe o sCdCodigo
if (frmPesquisa.ShowDialog() == DialogResult.OK)
{
bLocalizar = (frmPesquisa.sCdCodigo != string.Empty);
//verifico agora se meu bLocalizar retornou algum registro
if (bLocalizar)
{
_nCodGenerico = int.Parse(frmPesquisa.sCdCodigo);
}
}
return bLocalizar;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Carrega Valores

public override void CarregaValores()


{
try
{
//Instancio a classe e o DataRow, que recebe o mtodo PesquisaID de minha classe
AcessoDadosConsulta objConsulta = new AcessoDadosConsulta(_nCodGenerico);
DataRow dr = objConsulta.PesquisaID();
//Se o DataRow for diferente de nulo, preencho as propriedades
if (dr != null)
{
dtConsulta.Value = DateTime.Parse(dr["DATACONSULTA"].ToString());
dtHrInicio.Value = DateTime.Parse(dr["HORAINICIO"].ToString());
dtHrFim.Value = DateTime.Parse(dr["HORAFIM"].ToString());
txtObservacoes.Text = dr["OBSERVACOES"].ToString();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Se apertarmos F5 e para compilar teremos um erro no frmPesquisa, pois teremos que alterar a
chamada classe AcessoDadosConsulta, j que agora ele espera um valor do tipo int como
parmetro. Para resolver s passar o valor 0 e compilar a aplicao sem problemas.
74

Agora nos surge um problema. Se clicarmos no boto Localizar do frmCadastroHerdado, o


mesmo no ir carregar o nome do mdico e o nome do paciente em nossa tela. Para
resolvermos isso teremos que alterar nosso DataSet, incluindo assim novos campos para que, ao
clicarmos no boto Localizar, ele nos retorne os nomes do mdico e do paciente.
isso que faremos na prxima parte do nosso Consultrio, alterando no s o DataSet, como
tambm os mtodos criados acima.
Ol pessoal, nesta parte iremos continuar nosso sistema da onde paramos, ou seja, lembram-se
que ao clicarmos no boto Localizar do frmCadastroHerdado, ele no carregava o nome do
mdico e o nome do paciente em nossa tela? Ento, vamos resolver isso alterando
nosso DataSet de Pesquisas. Veremos tambm como usar LINQ em um de nossos formulrios.
Acompanhem:
Perceba que nosso DataSet j contm os nomes do Mdico e do Paciente:

Mesmo assim, precisamos alter-lo para incluir mais informaes. Nosso DataTable dever trazer
todos os campos do ConsultaDataTable. Dito isto, altere a query de consulta do PesquisaID como
na imagem abaixo:

Faa o mesmo para os outros trs TableAdapters de nosso DataTable, alterando a


instruo SELECT. O PesquisaDataTable dever ficar com este aspecto final:

Ok, agora vamos ao nosso frmConsultaHerdado e vamos alterar o mtodo Carrega Valores:
75

public override void CarregaValores()


{
try
{
//Instancio a classe e o DataRow, que recebe o mtodo PesquisaID de minha classe
AcessoDadosConsulta objConsulta = new AcessoDadosConsulta(_nCodGenerico);
DataRow dr = objConsulta.PesquisaID();
//Se o DataRow for diferente de nulo, preencho as propriedades
if (dr != null)
{
dtConsulta.Value = DateTime.Parse(dr["DATACONSULTA"].ToString());
dtHrInicio.Value = DateTime.Parse(dr["HORAINICIO"].ToString());
dtHrFim.Value = DateTime.Parse(dr["HORAFIM"].ToString());
txtObservacoes.Text = dr["OBSERVACOES"].ToString();
txtNomeMedico.Text = dr["NOMEMEDICO"].ToString();
txtNomePaciente.Text = dr["NOMEPACIENTE"].ToString();
_nCodMedico = int.Parse(dr["IDMEDICO"].ToString());
_nCodPaciente = int.Parse(dr["IDPACIENTE"].ToString());
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Percebam que j deixei preenchido o cdigo do Mdico e do Paciente, para que, na hora em que
o usurio for salvar o registro no banco, no d erro, j que os cdigos devem vir preenchidos no
momento em que o usurio faz a respectiva consulta.
Aperte F5 para compilar, v tela de Consulta, clique em Localizar para testar se nosso
mtodo CarregaValores est correto. Selecione uma consulta, clique em OK e veja o resultado:

No mtodo Salvar, apenas inclua a seguinte linha, antes do bSalvar:


objConsulta.bAtivo = true;
bSalvar = (objConsulta.Salvar(sStatus == StatusCadastro.scInserindo));

76

Assim, passamos o valor true ao campo Ativo, indicando que, no momento em que o registro
criado, a Consulta est ativa no sistema.
Mude algum dado, clique em Salvar e perceba que o registro tambm est sendo alterado com
sucesso. Teste as demais funcionalidades do sistema e veja que est tudo funcionando
corretamente.

Chega de conceitos, vamos prtica! Usaremos o LINQ na tela de Pesquisa de Pacientes.


Antes de alterarmos o mtodo Pesquisar, do frmPesquisaPaciente, precisamos fazer uma
alterao na classe de Acesso a Dados. Abra ela, v classe AcessoDadosConsulta, copie o
mtodo, do tipo DataTable, Pesquisar, cole-o na classe AcessoDadosPaciente e altere seu
mtodo, como o cdigo abaixo ilustra:
public DataTable Pesquisar()
{
try
{
//instancio o TableAdapter e o DataTable
dsConsulta.PacienteDataTable dt = new dsConsulta.PacienteDataTable();
PacienteTableAdapter ta = new PacienteTableAdapter();
//uso o mtodo Fill do TableAdapter, passando como parmetro o DataTable
ta.Fill(dt);
//retorno o DataTable preenchido
return dt;
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Assim temos um mtodo que nos retorna todos os dados do Paciente (por meio do mtodo Fill,
do TableAdapter).
Agora sim, abra o frmPesquisaPaciente e altere o mtodo Pesquisar para o seguinte (explicaes
a seguir):
//instancio a Classe e o DataTable, que recebe o mtodo Pesquisar
AcessoDadosPaciente acesso = new AcessoDadosPaciente();
DataTable dt = acesso.Pesquisar();
var consulta = from c in dt.AsEnumerable()
where
(c.Field<string>("NOMEPACIENTE").Contains(txtPesquisa.Text))
select new
{

77

_nCodPaciente = c.Field<int>("IDPACIENTE"),
_sNomePaciente = c.Field<string>("NOMEPACIENTE")
};

Obs: lembre-se de declarar o namespace System.Linq.


Comeo

declarando

uma

varivel

chamada

consulta,

passando

alias c in

(em) dt.AsEnumerable(), uso este AsEnumerable, que implementa a interface IEnumerable, para
indicar que estou pesquisando em uma coleo. S esta primeira linha j me retorna todos os
dados do Paciente.
Mais preferi filtrar, ento uso o

where(c.Field<string>(NOMEPACIENTE).Contains(txtPesquisa.Text)),

(lembrando que o c meu alias) uso o Field porque estou pesquisando dentro de um DataTable,
se fosse por exemplo, dentro de uma coleo no precisaria do Field. Como estou passando o
tipo string na pesquisa, isso me permite usar o mtodo Contains (semelhante ao Like do SQL),
assim posso refinar minha pesquisa. No parmetro do Contains, que espera uma string, passo
meu txtPesquisa.Text, assim ele ir pesquisar somente o valor digitado pelo usurio neste campo.
Aps isso, uso o select new para tipar os campos que vou retornar em minha pesquisa, ou seja,
indico quais campos sero exibidos na pesquisa, atribuindo seus respectivos tipos (int, string...).
Eu poderia usar apenas select c; mais assim no teria os campos tipados. Logo aps, fao o
mesmo que fiz acima, passando o Field, com seu tipo e a respectiva coluna que receber seu
valor.
Pronto, agora minha varivel consulta contm os dados da consulta com seus filtros. Agora s
eu jogar essa varivel dentro de um lao foreach para exibir seus resultados no ListView. Fao
desta forma:
lstPesquisa.Items.Clear();
foreach (var registro in consulta)
{
ListViewItem item = new ListViewItem();
item.Text = registro._nCodPaciente.ToString();
item.SubItems.Add(registro._sNomePaciente);
lstPesquisa.Items.Add(item);
}
Perceba que meu foreach ficou parecido com o do mtodo CarregarItens, do frmPesquisaBase.
Veja abaixo como ficou meu mtodo completo:
public override void Pesquisar()
{
try
{
AcessoDadosPaciente acesso = new AcessoDadosPaciente();
DataTable dt = acesso.Pesquisar();
if (rbtCodigo.Checked)

78

{
var consulta = from c in dt.AsEnumerable()
where

(c.Field<int>("IDPACIENTE")

==

int.Parse(txtPesquisa.Text))
select new
{
_nCodPaciente = c.Field<int>("IDPACIENTE"),
_sNomePaciente = c.Field<string>("NOMEPACIENTE")
};
lstPesquisa.Items.Clear();
foreach (var registro in consulta)
{
ListViewItem item = new ListViewItem();
item.Text = registro._nCodPaciente.ToString();
item.SubItems.Add(registro._sNomePaciente);
lstPesquisa.Items.Add(item);
}
}
else
{
var consulta = from c in dt.AsEnumerable()
where
(c.Field<string>("NOMEPACIENTE").Contains(txtPesquisa.Text))
select new
{
_nCodPaciente = c.Field<int>("IDPACIENTE"),
_sNomePaciente = c.Field<string>("NOMEPACIENTE")
};
lstPesquisa.Items.Clear();
foreach (var registro in consulta)
{
ListViewItem item = new ListViewItem();
item.Text = registro._nCodPaciente.ToString();
item.SubItems.Add(registro._sNomePaciente);
lstPesquisa.Items.Add(item);
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
}

Perceba que, no meu if, nossa consulta LINQ muda um pouco (na primeira linha da consulta),
mais nada muito complexo.

79

Salve e compile a aplicao. Clique em Pacientes e faa uma busca clicando no Localizar.
Busque por Nome e Cdigo e perceba que est funcionando corretamente. A diferena que com
LINQ nossas pesquisas so funcionais e performticas!
Abra a aplicao, v ao Solution Explorer e crie uma pasta, dando a ela o nome Relatrios. Ainda
no Solution Explorer adicione um novo formulrio, dando a ele o nome de frmPreview. Esse form
conter nosso relatrio.
Aplique

as

configuraes

padres

dos

outros

formulrios

nele

altere

propriedade WindowState para Maximized, para que ele sempre abra maximizado, o que faz mais
sentido para um relatrio.
Agora

ao ToolBox,

expanda

aba Reporting,

arraste

para

form

componente MicrosoftReportViewer. Abra sua SmartTag e clique na opo Dock in parent


container, para que o Relatrio preencha todo o formulrio. Seu form dever ficar parecido com o
da Figura 01:

Figura 01 Visualizao do Relatrio em branco no formulrio


Agora clique com o boto direito na pasta recm-criada e clique em Add > New Item. Selecione a
categoria Reporting, o template Report e d o nome de rptListagem.
Clique com o boto direito na parte cinza do seu relatrio e clique em Page Header e em Page
Footer, criando assim um Cabealho e um Rodap, respectivamente. Neles voc pode incluir
informaes relevantes para seu relatrio, como ttulo, data e hora, nmero da pgina, etc.
Abra a ToolBox e repare que seus controles mudaram, como mostra a Figura 02:

80

Figura 02 Controles da ToolBox, especficos para Relatrios


Veja uma breve descrio de cada um dos controles:
- TextBox = Na verdade este controle se assemelha com o Label, j que no podemos edit-lo
em tempo de execuo. Ele trabalha com expresses, que sero abordadas adiante;
- Line = Desenha uma linha no Relatrio;
- Table = Seria o GridView de nosso relatrio, onde podemos inserir valores vindos do banco.
Assim como no relatrio, no Table podemos inserir cabealho e rodap;
- Matrix = uma variao do Table, com dados agregados na forma de um GridView, com linhas
e colunas dinmicas;
- Rectangle = Desenha um retngulo, que serve como container de itens para o relatrio;
- List = Exibe uma coleo de itens do relatrio, que repetido para cada grupo ou linha de
dados;
- Image = Com este controle, podemos inserir quantas imagens desejarmos;
- Subreport = Este controle nos permite trabalhar com sub-relatrios em nosso relatrio;
- Chart = Com este controle, podemos inserir grficos em nosso relatrio.
Arraste um TextBox para o cabealho do relatrio e coloque um ttulo pra ele. Note que os
controles do Visual Studio so parecidos com o do Word para editar textos e aplicar formataes.
Da mesma forma podemos fazer o mesmo na aba Properties. Arraste tambm dois TextBoxes
para o rodap. Veja como ficou o relatrio na Figura 03:

81

Figura 03 Layout do Relatrio


Como dito anteriormente, vamos usar o recurso Expression, do TextBox, para formatarmos seus
valores. Para isso clique no TextBox esquerdo do rodap, v em Properties, clique em Value e
escolha <Expression>. Ir abrir o editor de expresses, que contm diversas propriedades
importantes, como data/hora, variveis globais, constantes, informaes como nmero de
pginas, entre outros.
Note que na tela acima das expresses, ele se parece com uma frmula do Excel, j que ele
sempre ir comear com o sinal de igual (=).
Obs: Para codificarmos uma expresso, devemos usar a sintaxe do Visual Basic. Dito isto,
vamos exibir a data de impresso atual, veja como na Figura 04:

Figura 04 Editor de Expresses do Visual Studio 2008


Note que eu concatenei, usando o operador de concatenao &, e dei uma formatao data,
para o formato brasileiro, que dia, ms e ano.
Altere a expresso do segundo TextBox, para o mesmo exibir uma paginao do relatrio, como
vemos na Figura 05:
82

Figura 05 Paginao para o Relatrio com Expresses


Agora precisamos vincular este arquivo rdlc (extenso padro deste tipo de relatrio) ao
meu frmPreview. Note que ao abrir a SmartTag do ReportViewer j temos o rdlc pronto para ser
selecionado, dentro de Choose Report.
Aps ter feito a vinculao, precisamos testar nosso Relatrio. Para isso, abra o
arquivo Program.cs e altere o formulrio inicial, que deve estar como frmMain, para frmPreview.
Aperte F5 para compilar e veja o resultado, que deve estar parecido com o da Figura 06:

Figura 06 Execuo do Relatrio, usando ReportViewer


Note que temos diversas funcionalidades nos botes acima, como consulta por palavras ou
frases e at a opo de exportar o relatrio para PDF e/ou planilha do Excel!
Vamos agora usar o controle Table, para retornar alguns registros do banco para nosso Relatrio.
Arraste-o para o relatrio e o formate como desejar.
Note que o Table tem a mesma estrutura do Relatrio, com cabealho, contedo e rodap, nos
dando a opo de adicionar quantas colunas/linhas desejarmos.
Expanda a aba Data Sources, note que ele contm nossos DataSets, criados nos artigos
anteriores, expanda o ltimo DataSet criado, aqui dei o nome a ele de dsConsulta, expanda a
tabela Pacientes e,

finalmente,

arraste

as

colunas IDPACIENTE, NOMEPACIENTE e TELEFONE para as colunas da linha Detail do Table.


Note que podemos realizar diversas formataes nos campos, como alterar cores, tamanho das
linhas, fontes, alinhamento, etc.
Finalizando, no Footer do Table, adicione um texto Total e, na coluna do meio, clique com o boto
direito nela e clique em Expression, para adicionarmos um totalizador dos registros.
83

Adicione a seguinte expresso:


Count(Fields!IDPACIENTE.Value, "dsConsulta_Paciente")

Usamos o operador Count, passando como parmetro a coluna que desejamos, no caso
a IDPACIENTE, e o nome de nosso DataSet.
Agora temos que ir ao frmPreview, abrirmos novamente a SmartTag do ReportViewer, ir
em Choose Report, clicar em <Server Report>, clicar novamente em Choose Report e clicar
no DataSet.
Devemos fazer isso porque da primeira vez no tnhamos vinculado dados do DataSet ao
relatrio, e agora que vinculamos fazemos isso pra dar um refresh no ReportViewer. Note que
ele adicionou na parte de baixo do form o DataSet, o TableAdapter e o BindingSource.
Agora aperte F5 para rodar o Relatrio e veja o resultado, como mostra a Figura 07:

Figura 07 Exibio do Report Viewer, carregado com dados do DataSet

84

Você também pode gostar