dezembro
2013
dezembro
2013
04
05
TvisualPlanit
incrementado como base para turbinar um novo
aplicativo – parte 1
Editorial
Autor: Hamden Voguel
Gerenciamento e
Manipulação de Dados com
Delphi
09
Autor: Jeferson Silva de Lima
18
ASP.NET MVC – Parte I
Índice
Autor: Luciano Pimenta
26
30
Dicas Delphi
Desafio The Club
dezembro
2013
03
Editorial
Caro Leitor,
Chegamos ao final de mais um ano e nossa equipe agradece cada associado por mais um ano de parceria com nosso clube. Cada ano que passa
o The Club se torna mais forte e tudo isto devemos a vocês. Procuramos
redigir uma revista com assuntos relevantes e sempre estando abertos
a sugestões. Este mês, nosso colaborador Luciano Pimenta discute um
assunto cada vez mais comum em nosso ramo, como devemos trabalhar
com Asp.Net envolvendo conceitos de MVC (Model View Controller) . Para
quem não sabe, MVC é um modelo de arquitetura de software que separa
a representação da informação da interação do usuário com o mesmo.
Esta primeira parte do artigo irá nos dar uma boa base para o aprendizado
desta tecnologia. Hamden Vogel nos apresenta uma melhoria na palheta de
componentes “TVisualPlanit”, nos componentes “TVpDayView”, “TVpMonthView”, “TVpContactGrid”. Artigo recomendado para quem deseja programar novos recursos em seus softwares. Nosso consultor técnico Jeferson
Silva de Lima, com o artigo “Gerenciamento e Manipulação de Dados com
Delphi”, nos ensina a manipular os dados dinamicamente tanto no contexto
do desenvolvedor como de usuário utilizando o Delphi XE 2, indispensável
para implementações alternativas ao decorrer do desenvolvimento de uma
aplicação. Depois de um tempo, estamos voltando com a seção de dicas e
truques de nossa revista. Neste mês possuímos dicas referentes ao Delphi
e ao Sistema Android.
Vou finalizando este editorial desejando a todos um Feliz Natal e que no
próximo ano nossa parceria continue firme e forte como sempre.
Av. Profº Celso Ferreira da Silva, 190
Jd. Europa - Avaré - SP - CEP 18.707-150
Informações e Suporte: (14) 3732-1529
Internet
http://www.theclub.com.br
Cadastro: [email protected]
Suporte: [email protected]
Informações: [email protected]
Skype Cadastro: theclub_cadastro
Skype Suporte: theclub_linha1
theclub_linha2
theclub_linha3
www.twitter.com/theclubbr
Copyright The Club 2013
Diretor Técnico
Marcos César Silva
Diagramação
Vitor M. Rodrigues
Design
Vitor M. Rodrigues
Revisão
Drielly Cristini Patrinhani
Colunistas
Hamden Vogel
Jeferson Silva de Lima
Luciano Pimenta
Thiago Cavalheiro Montebugnoli
Juninho
Jeferson Silva de Lima
Impressão e acabamento:
GRIL - Gráfica e Editora
Taquarituba-SP - Tel. (14) 3762-1345
Abraços
Reprodução
Thiago Montebugnoli - Editor Chefe
[email protected]
04
dezembro
2013
A utilização, reprodução, apropriação, armazenamento em banco
de dados, sob qualquer forma ou meio, de textos, fotos e outras
criações intelectuais em cada publicação da revista “The Club
Megazine” são terminantemente proibidos sem autorização
escrita dos titulares dos direitos autorais.
Delphi é marca registrada da Borland International,
as demais marcas citadas são registradas
pelos seus respectivos proprietários.
TvisualPlanit
incrementado como base para turbinar
um novo aplicativo – parte 1
Q
ue o Delphi contém componentes para mostrar e formatar
dados do tipo data/hora, todo mundo sabe. Mas um grid
associado a estas informações, exibindo no formato de
uma agenda, com um look customizável e dinâmico (visual
parecido com o MsOutlook) e com um gerenciamento
completo de “dados por data” - imagine um calendário mensal junto com um
outro diário, administrando seus eventos, contatos e lista de tarefas - pouca
gente sabe. E ainda com mais incrementações, como exibição de feriados no
calendário do componente, ativação de suas funções com um único clique do
mouse (muito mais eficiente - porque por padrão a maioria das funções tem
que dar um clique duplo), geração de calendário programado também dentro
do componente (exemplo: um paciente quer ser atendido todas as terças-feiras no mesmo horário, a partir da semana que vem, durante um período
de 6 meses) - aí creio que dessa forma automatizada não se tem registro para
este componente ou então um outro similar com estas características. Aí vem
a pergunta: porque não fazer? No caso, eu apresento o interessante pacote
de componentes em object Pascal chamado VisualPlanit desenvolvido pela
empresa TurboPower, concebido originariamente como produto comercial e
hoje mantido como projeto opensource. Uma suíte de componentes realmente
atrativa que automatiza procedimentos de data e hora com persistência de
dados. E para ilustrar, que tal desenvolver uma aplicação que faz uso desta
eficiente e conhecida tecnologia e com algumas alterações de minha parte,
para melhorar ainda mais os processos internos do componente, somado
ainda com algumas peculiaridades desta aplicação, como automatização da
criação de seu banco de dados, novas técnicas para geração de relatórios e
gráficos, registro da aplicação de trial para definitiva através de encriptação
de uma senha armazenada no Regedit do Windows, e muito mais? Pois tudo
isso será possível através da criação desta nossa nova aplicação de exemplo
real, chamada ProAgendus - Uma Agenda para uma Clínica Psicológica. E aqui
começamos o nosso trabalho - então mãos a obra!
A nossa aplicação conterá algumas características fundamentais:

Ela se “auto-conectará” com o nosso banco de dados através de
um algoritmo próprio;

Ela realizará procedimentos básicos e operacionais comuns a um
processo de agendamento de uma clínica psicológica fictícia (aqui é utilizado
o TVisualPlanit);

Ela validará o seu registro, funcionando em modo experimental até
que uma senha seja fornecida para sua liberação definitiva;

Ela gerará relatórios e gráficos, com opções de exportação;

Ela terá telas de cadastros necessários às realizações das atividades
do processo.
Entendendo a Aplicação: Primeiros Passos
Para a criação da nossa aplicação serão necessários alguns componentes,
listados abaixo:





TVisualPlanit - OpenSource;
DBISAM - Comercial;
XPMenu - Freeware;
TMaskeditHV - Freeware - Desenvolvido por mim;
XPMenu - Freeware.
O único que não é free nesta lista é o pacote DBISAM; trata-se de um
banco de dados desenvolvido pela empresa ElevateSoft e que para utilizá-lo
deve ser comprado por eles; entretanto pode-se baixar uma versão trial do
mesmo. Ele é necessário porque será o responsável pelo armazenamento
das informações (persistência) gerados pelo TVisualPlanit. Nós poderíamos
utilizar outros bancos disponibilizados pelo componente, como o Paradox
usando juntamente a BDE, mas para nossa melhor performance esse banco
foi eleito por mim devido a sua eficiência e também por uma questão de gosto
pessoal; já utilizei muito esse banco de dados e que o custo de distribuir uma
aplicação com ele é zero, já que ele não necessita de nenhuma DLL ou Client
para rodar junto com ele; entregando sua aplicação basta entregar apenas o
executável e as tabelas (funciona como um sistema de arquivos, mas os índices
dezembro
2013
05
são mantidos em memória). No nosso caso, para distribuir a aplicação iremos
entregar apenas o executável: nossa aplicação criará o arquivo de conexão
juntamente com as tabelas, onde o banco lerá um arquivo de configuração
de onde apontará onde estarão as tabelas.
Figura 01 - Fluxograma de Comunicação entre o ProAgendus e o Banco de Dados
DBISAM.
Primeiramente, é necessário compreender a lógica fundamental do
programa de como ele se “auto-configura” para setar nosso banco de dados,
criando e configurando pela primeira vez quando é chamado; podendo repetir
essa mesma lógica sempre quando houver perda de configuração. O programa
primeiramente acessa o arquivo “cfg.ini” onde tem o diretório do banco de
dados (uma pasta “BD”); se não existir esse arquivo ini o programa mesmo o
cria. Se o arquivo já existir, ele será lido para apontar o caminho do BD; se o
caminho for inválido será procurado de dentro do diretório atual da aplicação
em uma subpasta chamada BD, e se mesmo assim não existir o próprio banco
será criado automaticamente (extraindo um arquivo zipado contendo o banco
de dados e descompactando em uma subpasta no diretório atual do programa).
Figura 02.1 - Uma parte da função que procura todos os arquivos do BD.
Figura 03 - Tela Inicial do programa.
Chegamos ao ponto que mais nos interessa, que é a interação com os
componentes do pacote TVisualPlanit para geração de calendários no formato
de consulta por hora para um modelo de clínica particular de atendimento
psicológico.
Aqui, vamos detalhar mais o funcionamento da aplicação.
Tecnicamente falando, o TVisualPlanit utiliza a propriedade ControlLink
(passando como referência um objeto TVpControlLink) para fazer o papel
semelhante ao nosso conhecido TDataSource; fazendo então “uma ponte”
entre os componentes de acesso aos dados com um dataset especificado.
Funcionando assim:
Figura 04 - Representação básica de como o TVisualPlanit se interage com o seu
Banco de Dados utilizado.
Não entrarei em muitos detalhes da arquitetura desenvolvida pela TurboPower, pois isso já está largamente documentado por ela e disponibilizado
para download no site do sourceforge em: http://sourceforge.net
Primeiras interações com o TVisualPlanit
O nosso programa conterá apenas uma tela em que carregará todo o
processamento do componente TVisualPlanit, que é a tela de Agendamento
de Pacientes. Lá será feito toda a realização do processo. E lá serão exibidos
seus principais componentes, que são:
Figura 02 - Fluxograma de carregamento da aplicação.
06
dezembro
2013

TVpDayView: Exibe um calendário em formato de horas (horas de
um dia selecionado);

TVpMonthView: Exibe um calendário mensal. Lembra um pouco o
componente TMonthCalendar da VCL;

TVpContactGrid: Exibe todos os contatos de um usuário: de acordo
com o TVisualPlanit cada usuário de uma aplicação possui um ResourceID que
o identifica das outras persistências dos calendários.

TVpTaskList: Exibe uma lista de tarefas (como um “to-do list” ou um
simples bloco de anotações) onde o usuário anota qualquer coisa referente a
aplicação ou à algum processo.
DrawDays, utilizada internamente pelo componente TVpMonthView para o desenho,
tamanho, altura e demais posições da string informando que é dia de feriado.
Figura 05 - Tela de Marcação de Consultas (Agendamento), utilizando os componentes TVisualPlanit: da esquerda pra direita: TVpDayView, TVpMonthView, TVpContactGrid
e finalmente o TVpTaskList.
Os componentes mencionados acima foram todos alterados por mim. A
alteração do TVpMonthView foi a de exibir feriados e a de realizar as operações
principais do componente dando apenas um clique do mouse - (não é algo
simples; um certo trecho do código-fonte teve que ser alterado) - porque por
padrão tudo é ativado com um clique duplo; algo que incomoda se certas
operações forem executadas com grande frequência (imagina uma clínica
dentária de grande porte, onde para cada agendamento o usuário tivesse que
dar dois cliques para chamar operações básicas do programa).
Para verificar os feriados foi criada a seguinte função: IsHoliday (favor ver
figura abaixo nº6)
Figura 06 - Função IsHoliday; utilizada para verificar se o dia a ser impresso pelo
componente TVpMonthView é um potencial dia de trabalho ou se é um dia de feriado.
Figura 07 - Aplicação da função booleana IsHoliday chamada na procedure
Figura 08 - Componente TVpMonthView mostrando informações sobre feriados.
Pondo o Cadastramento de Sessões para funcionar na
prática:
A classe distribuída no pacote original do TVisualPlanit também foi modificada: a classe TDlgEventEdit, chamada para adicionar ou alterar sessões
(registros que atualizarão o TVpDayView e o TVpMonthView) foi bastante
alterada de modo a atender nossos novos requisitos; escolhe-se o paciente
(que obtém da tabela de pacientes), dados do agendamento (se está marcado
ou que depois foi desmarcado), plano de saúde e plano de agendamento.
Essa última informação (plano de agendamento) pode ser customizada de
modo a marcar como se fosse “pré-atendimentos”, ou seja, marcar um dia
da semana para várias semanas ou meses. Se não fosse isso, o paciente teria
que ser marcado de sessão em sessão, abrindo essa tela toda vez, tornando o
trabalho maçante. Um exemplo: “paciente José quer atendimento toda terça,
às 15:00 hrs” - com esse recurso bastaria preencher as opções do plano de
agendamento, simplificando todo o processo.
Figura 09 - Tela de Cadastramento de Sessões.
dezembro
2013
07
Outros recursos interessantes:
Além de marcar agendamentos, também é possível marcar tarefas, que
nada mais é do que anotar qualquer evento em um personalidado “bloco de
anotações”. Essa informação é também persistida em nosso banco, e salvando
em formato data, assim como toda a lógica do componente, e podendo ter a
opção de “terminar tarefa”. Esse componente é o TVpTaskList
Essa tela também utiliza o componente que eu desenvolvi chamado
TMaskeditHV, explicado em edições anteriores.
Interessante nesta tela é que o paciente é vinculado ao seu plano de saúde,
e em caso do plano não existir, ele pode ser acrescentado também. Ou seja,
um cadastro pode ser editado de dentro de outro. Pessoalmente, o que mais
gostei do processo de cadastro é que ele é chamado apenas com um clique
do mouse, e que outras validações também foram adicionadas, como CEP por
estado, email, estado e cidade.
Conclusão
Nesta primeira parte do artigo pudemos conferir alguns dos recursos implementados no pacote de componentes da “VisualPlanit”. Foram incrementadas
melhorias nos componentes: “TVpDayView”, “TVpMonthView”, “TVpContactGrid”, entre outros. Também começamos desenvolver uma aplicação que
coloca tudo que foi aprendido em prática. Encontramos-nos no mês que vem
para darmos procedência a este assunto, um Abraço!
Figura 10 - Tela de Anotações (tarefas a fazer).
Tela de Manutenção de Contato
Continuando, apresentaremos a tela de cadastro de contatos. Essa é a tela
que mais sofreu modificação do componente original, pois foi acrescentada
muitas informações que não tinham antes ou que tinham mas não atendia
pessoalmente aos requisitos de qualidade e eficiência.
Sobre o autor
Hamden Vogel
Analista de Sistemas pós-graduado em Engenharia de Software pela
UPIS e Programador Delphi com larga experiência desde 2000, tem desenvolvido e vendido softwares em Delphi para a África e Estados Unidos,
além do mercado nacional. Colaborou com dicas e componentes para sites
especializados em Delphi. Também desenvolve em outras linguagens como
C/C++, ASP, PHP e .NET.
[email protected]
Figura 11 - Tela de Cadastro de Contatos. Esses contatos serão utilizados para a
marcação de consultas.
08
dezembro
2013
Gerenciamento e Manipulação
de Dados com Delphi
Q
uando se trabalha com Delphi podemos a todo o momento
utilizar funções e procedimentos que diversas bibliotecas
nos disponibilizam, no entanto, em certas situações se
torna necessário criar ações que atendam necessidades
específicas.
Neste contexto iniciaremos nosso artigo. O intuito é apresentar formas de
manipular os dados dinamicamente tanto no contexto do desenvolvedor como
de usuário, vamos utilizar o Delphi XE2 para o exemplo, porém, a funcionalidade
pode ser aplicada para outras versões.
Formulário Principal
Inicie um novo projeto, File / New / VCL Forms Application - Delphi, nomeie
o formulário criado como ‘fmPadrao’ salve a aplicação coloque o nome da Unit
de ‘unPrincipal’ e o projeto vamos nomear de ‘Gerenciador’, após isso coloque
o componente ‘MainMenu’ para que possamos criar nosso menu Principal. O
menu deve ficar parecido com a imagem 1:
Biblioteca de Funções
Para que possamos prosseguir vamos criar nossa biblioteca de funções
que será responsável por abrigar os comandos que iremos utilizar durante a
execução da aplicação. Vá em File / New / Unit - Delphi, salve e nomeie o arquivo
como ‘unFuncoes’, feito isto podemos iniciar nossa codificação.
Nesta biblioteca os procedimentos serão responsáveis por realizar a
criação de nossa tabela além da manipulação dos dados que serão inseridos.
Em sua ‘Unit’ declare as bibliotecas que iremos utilizar, conforme listagem 1:
Listagem 1 – Uses.
Uses
System.SysUtils, System.
Classes, FMX.Dialogs, Vcl.
Forms, Data.SqlExpr, Datasnap.
DBClient, Data.DB, Vcl.
StdCtrls, StrUtils;
Nosso primeiro procedimento será responsável pela criação da tabela,
segue codificação na listagem abaixo:
Imagem 1 – Menu.
Listagem 2 – Procedimento Criar Tabela.
Imagem 2 – Tela Principal.
procedure CriarTabela(Client:
TClientDataSet; Campo: string;
Tipo: TFieldType; Tamanho:
Integer);
begin
if Tamanho = 0 then
begin
dezembro
2013
09
Client.FieldDefs.Add(Campo,
Tipo);
end
else
begin
Client.FieldDefs.Add(Campo,
Tipo, Tamanho, False);
end;
end;
Veja que na criação da tabela adicionamos os campos com suas especificações, no entanto para que a tabela seja realmente criada devemos inserir
o comando ‘ClientDataSet.CreateDataSet’, no entanto, a criação deve ser
feita após adicionarmos todos os campos e por isso o comando deve ficar
fora deste procedimento, ele será inserido em nosso formulário Base que
veremos mais a frente.
Com os campos inseridos no ‘ClientDataSet‘ já podemos inserir os dados
em nossa tabela temporária, lembre-se os dados ficarão em nosso ‘Client’
dinâmico, ou seja, ainda não foram salvos no banco de dados. A listagem 3
demonstra a manipulação dos dados para que sejam passados de nosso ‘Client’
temporário para o terminante.
Listagem 3 – Procedimento Inserir.
procedure Inserir(Client:
TClientDataSet; Formulario:
TForm);
var
CdsCopia: TClientDataSet;
I: Integer;
begin
CdsCopia := TClientDataSet.
Create(Formulario);
try
CdsCopia.CloneCursor(TClien
tDataSet(Client), True);
Client.Append;
for I := 0 to Client.
FieldCount - 1 do
begin
Client.Fields[I].Value :=
CdsCopia.FieldByName(Client.
Fields[I].FieldName).Value;
end;
finally
CdsCopia.Close;
CdsCopia.Free;
end;
end;
10
dezembro
2013
Para finalizar este processo devemos percorrer os registros de nosso
‘Client’ para efetuar a gravação em nossa base de dados, veja na listagem 4
como deve ser feito:
Listagem 4 – Procedimento Salvar.
procedure SalvarBD(ClientLocal,
ClientBanco: TClientDataSet);
var
I: Integer;
begin
ClientLocal.First;
while not ClientLocal.Eof do
begin
ClientBanco.Open;
ClientBanco.Append;
for I := 0 to ClientLocal.
FieldCount - 1 do
begin
if ClientBanco.Fields[I].
Tag = 0 then
begin
ClientBanco.Fields[I].
Value := ClientLocal.Fields[I].
Value;
end;
end;
ClientBanco.Post;
ClientLocal.Next;
end;
end;
Agora que os valores estão salvos apenas execute o ‘ApplyUpdates’ em
nosso ‘Client’, veremos isto também em nosso formulário base.
Você deve ter visto no inicio de nossa codificação alguns parâmetros que
passamos em nosso procedimento de criação da tabela como, por exemplo:
campo, tipo e tamanho. Para que esses parâmetros sejam passados corretamente criamos um procedimento chamado ‘LerCampos’ que irá pegar os
campos descritos pelo usuário em um Memo e realizar a criação de nossa
tabela, abaixo listagem 5 demonstra a leitura dos campos.
Listagem 5 – Procedimento Ler Campos.
procedure LerCampos(Client:
TclientDataSet; Lista: TMemo);
var
I, Tamanho, Contar, Max:
Integer;
Campo, Valor, Varchar,
Valorini: string;
Tipo: TFieldType;
begin
for I := 0 to Lista.Lines.
Count - 1 do
begin
Valorini := Lista.Lines[I];
Campo := Copy(Valorini, 1,
Pos(‘-’, Valorini) - 2);
Contar := Length(Campo) +
3;
Delete(Valorini, 1,
Contar);
Valor := Valorini;
Varchar := Copy(Valor, 1,
Pos(‘(‘, Valor) - 1);
if Varchar <> ‘’ then
Valor := Varchar;
case AnsiIndexStr(Valor,
[‘Integer’, Varchar, ‘Char’,
‘Date’]) of
0: begin
Tipo := ftInteger;
Tamanho := 0;
end;
1: begin
Tipo := ftString;
Max :=
Length(Valorini);
Tamanho :=
StrToInt(Copy(Valorini,
Pos(‘(‘, Valorini) + 1, Max Pos(‘(‘, Valorini) - 1));
end;
2: begin
Tipo := ftString;
Max :=
Length(Valorini);
Tamanho :=
StrToInt(Copy(Valorini,
Pos(‘(‘, Valorini) + 1, Max Pos(‘(‘, Valorini) - 1));
end;
3: begin
Tipo := ftDate;
Tamanho := 0;
end;
end;
CriarTabela(Client, Campo,
Tipo, Tamanho);
end;
end;
end.
Veja que neste exemplo estamos manipulando 4 tipos de dados (Integer,
String, Char e date), no entanto, outros campos podem ser adicionados caso
seja necessário. Utilizando o ‘Case AnsiIndexStr’ que já vimos em outros artigos,
vamos direcionar os dados de acordo com seu tipo. No final do procedimento
chamamos o ‘CriarTabela’ que irá conter todos os dados necessários para a
criação da tabela.
Formulário Base
Com nossa biblioteca criada vamos iniciar a codificação de nosso formulário
base. O layout do formulário deve ficar conforme imagem 3, veja que temos
um ‘Memo’ no qual passamos o valor de nossos campos, ou seja, vamos ter
apenas 1 formulário que será utilizado para todas as nossas tabelas.
Imagem 3 – Formulário de Cadastro.
Para que possamos cadastrar devemos além de indicar os campos apontarmos nossa tabela, veja que temos um ‘Combobox’ nele podemos encontrar
a lista com nossas tabelas, na listagem 6 temos a codificação para listar as
tabelas automaticamente.
Listagem 6 – OnShow do Formulário.
DM.Conexao.
GetTableNames(cbProvider.Items,
False);
Lembre-se nossa codificação está na Unit ‘unTabela_Temp’ que é o nosso
formulário base, ou seja, a Unit ‘unPadrao’ foi herdada e por isso iremos listar
os procedimentos que foram feitos no formulário pai, mas que serão executados no formulário filho.
Antes de iniciar verifique as Uses do Unit se estão conforme Listagem 7:
Listagem 8 – Botão Criar Tabela.
Uses
Vcl.Forms, Vcl.ExtCtrls, Data.
DB, Datasnap.DBClient, Vcl.
Controls, Vcl.StdCtrls, Vcl.
DBCtrls, Vcl.Grids, Vcl.
DBGrids, System.Classes,FMX.
dezembro
2013
11
Dialogs;
Implementation
Uses unFuncoes, unDM;
Listagem 7 – Uses.
No botão criar do formulário
base coloque a codificação
conforme listagem 8:
procedure TfmBase.
btnCriarTabelaClick(Sender:
TObject);
Var
I: Integer;
C: TComponent;
Begin
For I := 0 to ComponentCount
- 1 do
begin
C := Components[I];
if C is TClientDataSet then
begin
LerCampos(TClientDataSet(
C),Campos);
TClientDataSet(C).
CreateDataSet;
TClientDataSet(C).Open;
end;
end;
end;
if C is TClientDataSet then
begin
TClientDataSet(C).Close;
TClientDataSet(C).
FieldDefs.Clear;
end;
end;
cdsPadrao.ProviderName:=
‘dsp’+cbProvider.Text;
end;
Neste procedimento iremos limpar os dados nossos ‘Clients’ para que
possamos indicar o nome do ‘DataSetProvider’, veja que deixamos padrão para
que o nome inicie como ‘dsp’, portanto, lembre-se em seu ‘DataModule’ deixe
o nome de seus ‘DataSetProviders’ iniciando com ‘dsp’ assim pegamos o nome
da tabela conforme Listagem 6 que vimos anteriormente e adicionamos o ‘dsp.
Imagem 4 – DataModule.
Veja que nosso botão ‘Criar Tabela’ irá executar nosso procedimento feito
na biblioteca de funções no qual passamos nosso ‘Client’ e o ‘Memo’ que
nomeamos de ‘Campos’.
Listagem 9 – Evento OnSelect ComboBox (cbProviderSelect).
procedure TfmBase.
cbProviderSelect(Sender:
TObject);
Var
I: Integer;
C: TComponent;
Begin
For I := 0 to ComponentCount
- 1 do
begin
C := Components[I];
12
dezembro
2013
Após indicarmos os campos, tabela e realizarmos a criação podemos
inserir os dados. Portanto no evento ‘OnClick’ do ‘DbNavigator’ coloque a
Listagem conforme abaixo:
Listagem 10 – Evento OnClick DbNavigator.
if dsDinamico.State = dsInsert
then
begin
Inserir(cdsdinamico, fmBase);
end;
Neste evento chamamos o procedimento ‘Inserir’ que criamos anteriormente veja que passamos nosso ‘Client’ e o formulário ‘pai’ de nosso componente, ou seja, o formulário base.
Com os dados inseridos e gravados em memória podemos efetuar a
gravação em nosso banco de dados,
Listagem 11 – Botão Salvar.
procedure TfmBase.
btnSalvarClick(Sender:
TObject);
begin
SalvarBD(cdsdinamico,
cdsPadrao);
ShowMessage(‘Arquivos Salvos
com Sucesso!’);
end;
Para efetuar a gravação em nosso banco executamos o procedimento
‘SalvarBD’ que irá transferir os dados salvos em memória (cdsdinamico) para
nosso banco de dados (cdspadrao). Para finalizar a gravação devemos executar
o comando ‘ApplyUpdates’ em nosso ‘cdsPadrao’, veja na listagem 12:
Listagem 14 – Botão Fechar Tabela.
procedure TfmBase.
btnFecharTabelaClick(Sender:
TObject);
Var
I: Integer;
C: TComponent;
Begin
For I := 0 to ComponentCount
- 1 do
begin
C := Components[I];
if C is TClientDataSet then
begin
TClientDataSet(C).Close;
TClientDataSet(C).
FieldDefs.Clear;
end;
end;
ShowMessage(‘Tabela
Fechada!’);
end;
Listagem 12 – Evento After Post.
procedure TfmBase.
cdsPadraoAfterPost(DataSet:
TDataSet);
begin
cdsPadrao.ApplyUpdates(0);
end;
Com os dados devidamente gravados podemos limpar nossa tabela para
utilizamos novamente, portanto, utilize o comando da listagem 13 para remover
os valores que estão no ‘cdsdinamico’.
Listagem 13 – Botão Limpar Tabela.
procedure TfmBase.
btnLimparTabelaClick(Sender:
TObject);
begin
cdsdinamico.EmptyDataSet;
ShowMessage(‘Tabela Vazia!’);
end;
Outro comando que podemos utilizar caso seja necessário modificar a
tabela que estamos trabalhando é botão ‘Fechar Tabela’, ele irá fechar ambos os ‘Clients’ e limpar os campos que foram criados inicialmente. Veja na
listagem abaixo:
Para finalizarmos esta etapa no evento ‘OnClose’ do formulário vamos
fechar ambos os ‘Clients’ para que não fique nada em memória.
Listagem 15 – Evento OnClose.
procedure TfmBase.
FormClose(Sender: TObject; var
Action: TCloseAction);
begin
cdsdinamico.Close;
cdsPadrao.Close;
end;
Formulário de Configurações do Banco
Para deixarmos nossa aplicação ainda mais genérica criamos também
um formulário que será responsável por manipular as tabelas e campos de
nosso banco de dados.
Inicialmente crie um formulário e o layout deve ficar conforme Imagem 5.
Imagem 5 – Formulário Configurações do Banco.
dezembro
2013
13
Veja que nosso formulário possui um menu oculto que só será exibido
quando criarmos uma nova tabela (Imagem 6). Adicione também um componente ‘SQLQuery’ que será responsável por executar as instruções que
manipularão nossa base de dados.
:= False;
edtNomedaTabela.Text :=
UpperCase(Nome_Tab);
end;
end;
end;
end;
Veja que em nosso menu expandido temos que passar os dados para a
criação da tabela e em seguida podemos cria-la ou cancelar o processo, veja
abaixo a listagem de criação.
Imagem 6 – Formulário Configurações do banco (Criação da Tabela).
Ao clicar no botão ‘Nova * ’ do painel ‘Tabela’ iremos primeiro passar o
nome de nossa nova tabela e neste momento será verificado se a mesma já
existe, feito a verificação o painel de cadastro será exibido no rodapé do formulário conforme imagem 6. Listagem abaixo demonstra o processo.
Listagem 16 – Botão Nova Tabela.
procedure TfmBanco.
sbtnNovaTabelaClick(Sender:
TObject);
var
Nome_Tab: string;
begin
Nome_Tab := InputBox(‘Nova
Tabela’, ‘Nome: ‘, ‘’);
if Nome_Tab <> ‘’ then
begin
try
begin
SQLQuery.Close;
SQLQuery.SQL.Text :=
‘Select * From ‘ + Nome_Tab;
SQLQuery.Open;
ShowMessage(‘Tabela Já
Existe’);
SQLQuery.Close;
end;
except
if MessageDlg(‘Tabela Não
Encontrada!, Deseja Criar ?’,
mtConfirmation, [mbYes, mbNo],
0) = mrYes then
begin
fmBanco.Height :=
fmBanco.Height + Painel_
NovaTabela.Height + 10;
Painel_Campos.Visible
14
dezembro
2013
Listagem 17 – Botão Criar Tabela.
procedure TfmBanco.
sbtnCriarClick(Sender:
TObject);
begin
// Sintaxe -> CREATE TABLE
TABELA (PK INTEGER)
SQLQuery.Close;
SQLQuery.SQL.Text := ‘’;
SQLQuery.SQL.Text := ‘Create
Table ‘ + edtNomedaTabela.Text
+ ‘ ( ‘ + edtPk.Text + ‘ ‘ +
cbTipo.Text + ‘ NOT NULL) ‘;
SQLQuery.ExecSQL();
// Sintaxe -> ALTER TABLE
TABELA ADD CONSTRAINT PK_CODIGO
PRIMARY KEY (CODIGO)
SQLQuery.SQL.Text := ‘’;
SQLQuery.SQL.Text := ‘ALTER
TABLE ‘ + edtNomedaTabela.Text
+ ‘ ADD CONSTRAINT ‘ + ‘PK_’
+ edtNomedaTabela.Text + ‘
PRIMARY KEY (‘ + edtPk.Text +
‘)’;
SQLQuery.ExecSQL();
ShowMessage(‘Tabela Criada
com Sucesso!’);
cbTabelas.Text := ‘’;
cbTabelas.Items.Clear;
fmBanco.OnShow(nil);
fmBanco.Height := fmBanco.
Height - Painel_NovaTabela.
Height - 10;
Painel_Campos.Visible :=
True;
edtNomedaTabela.Text := ‘’;
end;
Caso o usuário não queira mais criar a tabela, pode utilizar o botão ‘Cancelar’ para voltar o formulário ao estado inicial. Processo do botão ‘Cancelar’
na listagem abaixo:
Listagem 18 – Botão Cancelar.
procedure TfmBanco.
sbtnCancelarClick(Sender:
TObject);
begin
fmBanco.Height := fmBanco.
Height - Painel_NovaTabela.
Height - 10;
Painel_Campos.Visible :=
True;
edtNomedaTabela.Text := ‘’;
end;
Em nosso formulário temos um ‘Combobox’ nomeado de ‘cbTabelas’ ele
será responsável por listar todas as tabelas que de nosso banco, listagem 19
demonstra o procedimento.
SQLQuery.Close;
SQLQuery.SQL.Text :=
‘Drop Table ‘ + Nome_Tab;
SQLQuery.ExecSQL();
ShowMessage(‘Tabela
Excluída com Sucesso!’);
cbTabelas.Text := ‘’;
cbTabelas.Items.Clear;
fmBanco.OnShow(nil);
end;
except
ShowMessage(‘Erro ao
Excluir!’);
end;
end;
end;
Para finalizarmos vamos manipular nossos campos, veja que temos um
painel intitulado de ‘Campo’. Para que possamos acessar as propriedades deste
painel primeiramente devemos selecionar o nome de nossa tabela, após isso
o ‘Combobox’ ‘Existentes’ irá exibir o nome dos campos da tabela indicada.
Veja abaixo o comando para listar os campos:
Listagem 19 – Evento OnShow.
Listagem 21 – Evento OnSelect Combobox(cbTabelas).
procedure TfmBanco.
FormShow(Sender: TObject);
begin
DM.Conexao.
GetTableNames(cbTabelas.Items,
False);
end;
procedure TfmBanco.
cbTabelasSelect(Sender:
TObject);
begin
DM.Conexao.
GetFieldNames(cbTabelas.Text,
cbExisCampo.Items);
end;
Podemos excluir as tabelas que já possuímos em nossa base de dados com
um comando ‘Drop Table’ veja como ficou nosso processo na listagem abaixo:
Listagem 20 – Botão Excluir.
procedure TfmBanco.
sbtnExcluirTabelaClick(Sender:
TObject);
var
Nome_Tab: string;
begin
Nome_Tab := InputBox(‘Excluir
Tabela’, ‘Nome: ‘, ‘’);
if Nome_Tab <> ‘’ then
begin
try
begin
// Sintaxe -> DROP TABLE
TABELA
Neste contexto o usuário poderá adicionar um novo campo, alterar
ou excluir um já existente. Por este motivo vamos demonstra cada um dos
processos citados (Inclusão, alteração e exclusão). Veja na listagem 22 temos
alguns blocos de comando para a criação dos campos, foram feitos 4 tipos, que
podem variar de ‘Nulo’ para não ‘Nulo’ e numérico para texto.
Listagem 22 – Botão Novo Campo.
procedure TfmBanco.
sbtnNovoCampoClick(Sender:
TObject);
begin
// Sintaxe -> ALTER TABLE
TABELA ADD CAMPO VARCHAR(50)
SQLQuery.Close;
SQLQuery.SQL.Text := ‘’;
dezembro
2013
15
if (CheckNull.Checked =
False) and (cbcTipo.Text <>
‘INTEGER’) and (cbcTipo.Text <>
‘FLOAT’) and (cbcTipo.Text <>
‘DATE’) then
begin
SQLQuery.SQL.Text := ‘ALTER
TABLE ‘ + cbTabelas.Text + ‘
ADD ‘ + edtNomeCampo.Text +
‘ ‘ + cbcTipo.Text + ‘(‘ +
edtTamanhoCampo.Text + ‘)’;
end;
if (CheckNull.Checked = True)
and (cbcTipo.Text <> ‘INTEGER’)
and (cbcTipo.Text <> ‘FLOAT’)
and (cbcTipo.Text <> ‘DATE’)
then
begin
SQLQuery.SQL.Text := ‘ALTER
TABLE ‘ + cbTabelas.Text + ‘
ADD ‘ + edtNomeCampo.Text +
‘ ‘ + cbcTipo.Text + ‘(‘ +
edtTamanhoCampo.Text + ‘) NOT
NULL’;
end;
if (CheckNull.Checked = True)
and (cbcTipo.Text = ‘INTEGER’)
or (cbcTipo.Text = ‘FLOAT’) or
(cbcTipo.Text = ‘DATE’) then
begin
SQLQuery.SQL.Text := ‘ALTER
TABLE ‘ + cbTabelas.Text + ‘
ADD ‘ + edtNomeCampo.Text + ‘ ‘
+ cbcTipo.Text + ‘ NOT NULL’;
end;
if (CheckNull.Checked =
False) and (cbcTipo.Text =
‘INTEGER’) or (cbcTipo.Text
= ‘FLOAT’) or (cbcTipo.Text =
‘DATE’) then
begin
SQLQuery.SQL.Text := ‘ALTER
TABLE ‘ + cbTabelas.Text + ‘
ADD ‘ + edtNomeCampo.Text + ‘ ‘
+ cbcTipo.Text;
end;
SQLQuery.ExecSQL();
cbExisCampo.Items.Clear;
cbTabelas.OnSelect(nil);
ShowMessage(‘Campo “’ +
edtNomeCampo.Text + ‘” criado
com Sucesso!’);
end;
16
dezembro
2013
Em alguns casos o usuário deseja remover um campo que já não utiliza
mais, e por este motivo programamos o botão ‘Excluir’, veja listagem 23. Entretanto podemos também reutilizar um campo que já está inserido em nossa
tabela, porém necessitamos alterar o nome do mesmo, pensando nisso criamos
o procedimento para alteração do campo, veja na Listagem 24.
Listagem 23 – Botão Excluir Campo.
procedure TfmBanco.
sbtnExcluirCampoClick(Sender:
TObject);
begin
// Sintaxe -> ALTER TABLE
“TABELA” DROP “CAMPO”
try
SQLQuery.Close;
SQLQuery.SQL.Text := ‘’;
SQLQuery.SQL.Text := ‘ALTER
TABLE “’ + cbTabelas.Text + ‘”
DROP “’ + cbExisCampo.Text +
‘”’;
SQLQuery.ExecSQL();
ShowMessage(‘Campo “’ +
cbExisCampo.Text + ‘” Excluído
com Sucesso!’);
cbExisCampo.Text := ‘’;
cbExisCampo.Items.Clear;
cbTabelas.OnSelect(nil);
except
ShowMessage(‘Erro ao
Excluir campo!’);
end;
end;
Listagem 24 – Botão Alterar Campo.
procedure TfmBanco.
sbtnAlterarClick(Sender:
TObject);
var
Novo_Nome: string;
begin
// Sintaxe -> ALTER TABLE
TABELA ALTER COLUMN CAMPO TO
NOVO_NOME
try
Novo_Nome := InputBox(‘
Novo Nome ‘, ‘Nome:’,
cbExisCampo.Text);
if Novo_Nome = cbExisCampo.
Conclusão
Text then
begin
ShowMessage(‘Nome já
existe, favor verificar!’);
end
else
begin
SQLQuery.Close;
SQLQuery.SQL.Text := ‘’;
SQLQuery.SQL.Text :=
‘ALTER TABLE ‘ + cbTabelas.
Text + ‘ ALTER COLUMN ‘ +
cbExisCampo.Text + ‘ TO ‘ +
Novo_Nome;
SQLQuery.ExecSQL();
ShowMessage(‘Campo “’ +
cbExisCampo.Text + ‘” Alterado
com Sucesso!’);
cbExisCampo.Text := ‘’;
cbExisCampo.Items.Clear;
cbTabelas.OnSelect(nil);
end;
except
ShowMessage(‘Erro ao
Alterar!’);
end;
end;
O intuito do artigo é demonstrar como podemos trabalhar com o Delphi de
forma dinâmica, no que envolve desenvolvedor e usuário, visando demonstrar
de forma simples como aplicar funcionalidades alternativas, portanto, o leitor
fica livre para melhorar e implementar da forma que desejar.
Espero que tenham gostado desta dica e até a próxima!
Sobre o autor
Jeferson Silva de Lima
Consultor The Club.
[email protected]
dezembro
2013
17
ASP.NET MVC
V
ocê já deve ter ouvido falar de ASP.NET. É uma arquitetura
Web para criar sites, portais, aplicações Web. Mas você sabe
o que é ASP.NET MVC? Em termos gerais tem a mesma finalidade: criar sites, portais, aplicações Web etc, mas com um
conceito diferente do ASP.NET “original” (também chamado
Web Forms).
O ASP.NET MVC é baseado no padrão MVC (Model View Controller), criado
pela Xerox nos anos 70. Nesse padrão, é feita uma separação de responsabilidades nas camadas da aplicação (modelo, visão e controlador). Neste artigo
quero mostrar as características do ASP.NET MVC para o leitor que não conhece,
assim como mostrar dicas para desenvolvedores que já usam a arquitetura.
Parte I
Primeiro projeto
Após essa pequena explanação, vamos entender como funciona o ASP.NET
MVC na prática. Criaremos exemplos usando o Visual Studio 2012 e a versão
ASP.NET MVC 4. Os exemplos também podem ser feitos no Visual Studio 2010
(você deve instalar a versão 4 do ASP.NET MVC em separado).
No Visual Studio 2013, já temos a versão ASP.NET MVC 5. Crie um novo
projeto ASP.NET MVC 4 Web Application no Visual Studio 2012 (Figura 1).
MVC x WebForms
Como sempre, temos um comparativo sobre características do Web
Forms e MVC.
•
Web Forms: presente desde 2001, sendo o primeiro modelo de
desenvolvimento do .NET e o mais utilizado atualmente. Tornou ágil o desenvolvimento de aplicações Web, usando o conceito “drag and drop” (arrastar e
soltar).
Possui grandes opções de controles de tela, onde o HTML e funções JavaScript são criadas “sozinhas”. Entres os contras dessa arquitetura podemos
destacar: pouco controle sobre o HTML e JavaScript gerado, impossibilidade
de testes de interface, difícil integração com frameworks de JavaScript.
•
MVC: padrão de desenvolvimento MVC, faz a separação de responsabilidades das camadas da aplicação, controle total sobre o HTML e JavaScript
gerado, podemos criar testes de interface, etc. Entre os pontos negativos:
não é RAD, não tem controles prontos, necessidade de aprendizado (modelo
totalmente diferente do Web Forms), desenvolvimento maior de código.
O que as duas arquiteturas tem em comum? Rodam sobre o mesmo
runtime (ASP.NET), geram páginas ASPX, rodam no IIS, tem o mesmo acesso a
dados (LINQ, ADO.NET, Entity Framework) e desenvolvidos utilizando o Visual
Studio. Ou seja, sua aplicação Web Forms, ao ser “convertida” para MVC, vai
rodar normalmente no servidor.
18
dezembro
2013
Figura 1. Criando um projeto ASP.NET MVC no Visual Studio 2012
Após, será aberto um editor onde escolheremos o template de projeto
que podemos criar (Figura 2):
•
Empty: projeto vazio (sem scripts, arquivos de imagens etc);
•
Basic: projeto onde temos o básico da estrutura de pastas de um
projeto ASP.NET MVC;
•
Internet Application: cria um projeto com autenticação usando
Forms Authentication;
•
Intranet Application: cria um projeto com autenticação usando
Windows Authentication;
•
Mobile Application: cria um projeto para aplicações mobile;
•
Web API: cria um projeto API para expor métodos onde outros sites
irão consumir.
Figura 2. Escolhendo o template de projeto ASP.NET MVC
Como podemos ver na Figura 2, temos mais templates disponíveis, de
acordo com a instalação de plug-ins e frameworks de terceiros. Em View
Engine escolha Razor.
View engine é o responsável pela criação do HTML. Temos dois tipos:
Razor e ASPX. Razor é mais enxuta e praticamente é C#, já o ASPX, usa tags de
scripts para a criação do HTML. Veja na Listagem 1, exemplos de Razor e ASPX.
Listagem 1. Diferenças entre Razor e ASPX
Razor
@{
string nome = “Luciano
Pimenta”;
int numero = 0;
}
ASPX
<%
string nome = “Luciano
Pimenta”;
int numero = 0;
%>
No decorrer do artigo, veremos como funciona a engine Razor. Vamos
escolher o template Basic para que possamos ter a estrutura básica de uma
aplicação ASP.NET MVC.
Model View Controller
Na Figura 3 temos a estrutura da nossa aplicação.
Figura 3. Estrutura de uma aplicação basic para o ASP.NET MVC
Semelhante a uma aplicação ASP.NET Web Forms, temos várias pastas,
mas temos três que são essenciais: Models, Views e Controllers. Na pasta
Views temos as páginas (com extensão cshtml). Já em Controllers teremos as
classes responsáveis pelas regras de negócios e em Models temos as classes
de mapeamento do banco de dados.
Vamos entender um pouco sobre MVC. O padrão MVC foi criado pela
Xerox em meados dos anos 70 e tem como principal caraterísticas separar as
responsabilidades das camadas da aplicação. Temos um exemplo simples de
como funciona o padrão na Figura 4.
Figura 4. Conhecendo o padrão de projeto MVC. Fonte: www.oficinadanet.com.br
O Model é responsável por “pegar” os dados do banco e disponibilizar
para o Controller. Este por sua vez, “envia” os dados para a View e recebe
novamente, repassando para o Model. O Controller também é responsável
pela validação dos dados antes de enviar ao Model.
A View recebe os dados do Controller e exibe em tela, devolvendo para o
Controller os dados alterados ou inseridos quando assim for solicitado. Veja
que as responsabilidades são claras, não veremos em projeto ASP.NET MVC,
código em páginas ASPX com comandos SQL no banco de dados, por exemplo.
dezembro
2013
19
Nota: isso não é correto nem em aplicação ASP.NET Web Forms,
mas as primeiras aplicações tinham resquícios do ASP3.
Assim, sabemos que validações dos dados devem ser feitas no Controller,
deixando a View com a responsabilidade de apenas exibir os mesmos. Como
primeiro exemplo, vamos aprender como passar dados do Controller para a
View, algo bastante comum no ASP.NET MVC.
Para aprender isso, precisamos primeiro entender como o Controller
trabalha com a View.
Trafegando dados entre Controller e View
Quando precisamos passar dados (independente se sejam oriundos de
banco de dados ou não), podemos usar o ViewBag ou ViewData. ViewData
podemos comparar com uma variável de sessão (objeto Session) do ASP.NET.
Podemos preencher no Controller e recuperar seu valor na View. Já o
ViewBag é um objeto bem mais robusto onde podemos criar propriedades
dinâmicas. Ou seja, podemos indicar o valor que queremos atribuindo a uma
propriedade e na View apenas referenciar essa propriedade. Vamos a um
exemplo.
No projeto criado, clique com o botão direito na pasta Controllers e escolha
Add>Controller. No editor (Figura 5), vamos dar o nome de “HomeController”.
Rotas
No ASP.NET MVC temos o conceito de rotas usando o ASP.NET Routing
para rotear URLs. Uma rota indica: um Controller, uma Action e um parâmetro
(opcional). Não temos mais URLs, como: localhost/NomeProjeto/Index.aspx
ou localhost/NomeProjeto/Index.aspx?codigo=1. Agora teremos: localhost/
NomeProjeto/Index ou localhost/NomeProjeto/Index/1.
Podemos dizer que a URL ficou mais amigável e mais fácil de compreensão.
Index é a rota padrão de uma aplicação ASP.NET MVC. Todo Controller deve
ter um método chamado Index (customizações são permitidas).
No arquivo RouteConfig.cs na pasta App_Start podemos ver o mapeamento
da rota (Listagem 2).
Listagem 2. Mapeamento de rotas no RouteConfig
public static void
RegisterRoutes(RouteCollection
routes)
{
routes.
IgnoreRoute(“{resource}.axd/
{*pathInfo}”);
routes.MapRoute(
name: “Default”,
url: “{controller}/
{action}/{id}”,
defaults: new { controller
= “Home”, action = “Index”,
id = UrlParameter.
Optional }
);
}
O RegisterRoutes é chamado apartir do Application_Start do Global.
asax.cs.
20
dezembro
2013
Figura 5. Criando um controller
Todo Controller criado já possui um método Index. No mesmo, temos o
retorno da View. Altere o Index padrão para o seguinte código:
ViewData[“HelloWorld”] = “Hello
World”;
ViewBag.Hello = “Hello”;
ViewBag.World = “World”;
Atribuímos para ViewData, de nome Hello, um valor. Na ViewBag, criamos
duas propriedades dinâmicas e preenchemos. Esses valores serão apresentados
na View. Clique com o botão direito na pasta Views e escolha Add>New Folder.
Dê o nome de “Home”. Padronizamos que as pastas dentro de Views devem
ter o mesmo nome dos Controllers.
Dentro da pasta Home, adicione uma View, clicando de direito e escolhendo Add>View. No editor (Figura 6), vamos dar um nome para a View: “Index”.
Mas e dados ou objetos, como fazer. Também é bastante simples. Vamos criar um Model. Clique com o botão direito na pasta Models e escolha
Add>Class. Dê o nome de “Pessoa.cs” para a nova classe e adicione as seguintes
propriedades:
public int PessoaID { get; set;
}
public string Nome { get; set;
}
public DateTime Nascimento {
get; set; }
As classes da pasta Models, servem para mapear objetos do banco ou
simplesmente ser um repositório. Vamos modificar o método Index do Home
para o código da Listagem 4.
Figura 6. Criando uma view
Ao criar a View, temos um arquivo cshtml (como se fosse um ASPX), onde
vamos codificar nossa página. Nela temos controle total do HTML, JavaSricpt,
etc. Altere o código para o da Listagem 3.
Listagem 3. Codificando a View
@{
ViewBag.Title = “Minha
página Index”;
}
<p>ViewData: <b>@
ViewData[“HelloWorld”]</b></p>
<p>Hello: <b>@ViewBag.Hello</
b></p>
<p>World: <b>@ViewBag.World</
b></p>
Note que usamos o caracter @ para invocar objetos na página. O Intelissense não funciona no ViewBag, por que as propriedades são dinâmicas.
Execute a aplicação e veja o resultado (Figura 7).
Listagem 4. Passando dados para a View
Pessoa pessoa = new Pessoa
{
PessoaID = 1,
Nome = “Luciano Pimenta”,
Nascimento = DateTime.Now
};
return View(pessoa);
O código é simples. Instanciamos uma classe Pessoa e repassamos esse
objeto para a View. Agora, precisamos receber esse objeto na View. Veja a
Listagem 5 para ver como foi modificada a View.
Listagem 5. Recebendo um objeto Pessoa na View
@model HelloWorld.Models.Pessoa
@{
ViewBag.Title = “Minha
página Index”;
}
<p><b>Id</b>: @Model.PessoaID</
p>
<p><b>Nome</b>: @Model.Nome</p>
<p><b>Nascimento</b>: @Model.
Nascimento</p>
Figura 7. Executando a aplicação
A primeira linha é importantíssima, pois nela indicamos qual model esta
sendo recebido pela página. Com a indicação do tipo de objeto, usamos o @
Model para trabalhar com o objeto recebido pela página, assim, podemos
dezembro
2013
21
exibir suas propriedades onde desejarmos. Teste a aplicação.
Nota: veja que para indicarmos o objeto que a página recebe usamos
o nome model em minúsculo. Para acessar as propriedades do objeto,
usamos em maiúsculo.
E se estivéssemos trabalhando com mais de um objeto (uma consulta
que retorna vários registros)? Como faríamos? Primeiro, vamos criar um novo
método no Controller, chamado “Lista” e retornar vários objetos pessoas em
uma lista. Veja na Listagem 6 o método Lista.
Listagem 6. Método Lista do HomeController
public ActionResult Lista()
{
Pessoa pessoa1 = new Pessoa
{
PessoaID = 1,
Nome = “Luciano Pimenta”,
Nascimento = new
DateTime(1976, 5, 8)
};
Pessoa pessoa2 = new Pessoa
{
PessoaID = 2,
Nome = “Alessandra
Pimenta”,
Nascimento = new
DateTime(1980, 6, 9)
};
Pessoa pessoa3 = new Pessoa
{
PessoaID = 3,
Nome = “Luciano Castro”,
Nascimento = new
DateTime(1978, 7, 22)
};
List<Pessoa> lista = new
List<Pessoa>();
lista.Add(pessoa1);
lista.Add(pessoa2);
lista.Add(pessoa3);
}
return View(lista);
Apenas criamos alguns objetos Pessoa e colocamos em uma lista, que é
repassada para a View. Crie uma nova View, na pasta Home, dando o nome
22
dezembro
2013
de “Lista”. Na View, vamos adicionar o código da Listagem 7.
Listagem 7. View que receberá a Lista de Pessoa
@model List<HelloWorld.Models.
Pessoa>
@{
}
ViewBag.Title = “Lista”;
<h2>Lista</h2>
<table>
<tr>
<th>Id</th>
<th>Nome</th>
<th>Nascimento</th>
</tr>
@foreach (var item in @
Model)
{
<tr>
<td>@item.
PessoaID</td>
<td>@item.Nome</td>
<td>@item.
Nascimento.ToString(“dd/MM/
yyyy”)</td>
</tr>
}
</table>
Note, que você desenvolvedor é o responsável por exibir os dados na
página. Não temos um Grid (componentes de terceiros nos auxiliam). A criação
do HTML esta tudo em suas mãos. Agora, não estamos recebendo apenas um
objeto Pessoa, mas sim um List<Pessoa>.
Criamos uma tabela com os cabeçalhos e usamos um foreach para percorrer a lista e exibir os dados. Para que possamos acessar a página da lista,
precisamos criar um link. Em Index, adicione o seguinte código (abaixo do
código do exemplo do Index):
@Html.ActionLink(“Lista”,
“Lista”, “Home”)
ActionLink ira redirecionar para a View que queremos. O primeiro parâmetro indica o texto do link. O segundo a Action que iremos usar e no terceiro,
será a rota. Execute a aplicação e veja o resultado (Figura 8).
Listagem 9. View para cadastro da pessoa
@model HelloWorld.Models.Pessoa
@{
}
ViewBag.Title = “Cadastro”;
<h2>Cadastro</h2>
Figura 8. Lista de pessoas da aplicação
Cadastro
Precisamos criar um cadastro. Vamos cadastrar uma pessoa e mostrar
os dados inseridos pelo usuário. Ainda não usaremos banco de dados, mas a
adaptação como veremos no próximo artigo, será muito simples. Veja o código
da Action na Listagem 8.
Listagem 8. Métodos de cadastro
[HttpPost]
public ActionResult
Create(Pessoa pessoa)
{
return View(“ExibeDados”,
pessoa);
}
[HttpGet]
public ActionResult Create()
{
return View();
}
A ideia é receber o objeto Pessoa como parâmetro e repassar para o Index.
Em uma aplicação real, iriamos inserir pessoa no banco de dados e depois
redirecionar para onde quisermos.
O ASP.NET MVC é capaz de montar objetos com os valores dos parâmetros
HTTP e passá-los como argumento para as ações dos controladores (por isso
usamos a marcação HttpPost no Create). Note que no objeto View, temos
alguns parâmetros, entre eles, de indicar o nome da View e o model que
queremos passar.
Crie uma View chamada “Create”, e uso o código da Listagem 9.
@using (Html.BeginForm())
{
<fieldset>
<legend>Cadastro</legend>
<div class=”display-label”>
@Html.
DisplayNameFor(model => model.
PessoaID)
</div >
<div class=”display-field”>
@Html.EditorFor(model
=> model.PessoaID)
</div >
<div class=”display-label”>
@Html.
DisplayNameFor(model => model.
Nome)
</div >
<div class=”display-field”>
@Html.EditorFor(model
=> model.Nome)
</div >
<div class=”display-label”>
@Html.
DisplayNameFor(model => model.
Nascimento)
</div >
<div class=”display-field”>
@Html.EditorFor(model
=> model.Nascimento)
</div >
</fieldset>
<p>
<input type=”submit”
value=”Cadastro” />
</p>
}
Como sabemos que teremos um objeto Pessoa na página, usamos @
Html.EditorFor para montar uma caixa de texto e @Html.DisplayNameFor
dezembro
2013
23
para exibir um rótulo.
Nota: No model, podemos marcar a propriedade para exibir o rótulo
que quisermos, por exemplo usando a marcação:
[Display(Name = “Código da
pessoa”)]
public int PessoaID { get; set;
}
Crie uma View chamada “ExibeDados” e implemente, semelhante ao
Index, onde recebemos um model Pessoa, somente para exibição. Adicione
um link no Index para ser direcionado ao cadastro criado anteriormente. Rode
a aplicação e faça o teste.
Validações
No ASP.NET Web Forms, temos controles para validações, os Validators.
Vou mostrar um exemplo, onde podemos validar os dados na Action do
controller. Veja na Listagem 10, como fazer essa validação (método Create).
Note que verificamos cada campo do objeto Pessoa (o que pode ser trabalhoso, dependendo da quantidade de campos validados). Quando a regra
é quebrada, adicionamos a mensagem de erro no ModelState.
Na View, precisamos ainda fazer uma última modificação. Abaixo de cada
controle de tela (EditorFor), precisamos colocar a indicação da validação do
campo. Adicione o seguinte código (alterando o nome do campo para os
demais):
@Html.ValidationMessageFor(model
=> model.PessoaID)
Na parte inferior da página (após o código HTML), vamos indicar a biblioteca jQuery que auxilia na exibição das validações:
@section Scripts{
@Scripts.Render(“~/bundles/
jqueryval”)
}
Listagem 10. Validando dados na Action do Controller
if (pessoa.PessoaID == 0)
ModelState.
AddModelError(“PessoaID”,
“Campo PessoaID:
preenchimento obrigatório.”);
if (string.IsNullOrEmpty(pessoa.
Nome))
ModelState.
AddModelError(“Nome”,
“Campo Nome: preenchimento
obrigatório.”);
if (pessoa.Nascimento == null)
ModelState.
AddModelError(“Nascimento”,
“Campo Nascimento:
preenchimento obrigatório.”);
if (ModelState.IsValid)
return View(“ExibeDados”,
pessoa);
return View();
24
dezembro
2013
Rode e teste a aplicação. Agora, vamos conhecer uma maneira bem mais
simples de validação, o DataAnnotations. Simplesmente, criamos uma marcação na propriedade do model, indicando o que queremos validar. Veja na
Listagem 11 algumas validações de Pessoa.
Listagem 11. Validações com DataAnnotations
[Required(ErrorMessage=”Campo
PessoaID: preenchimento
obrigatório”)]
[Display(Name=”Código da
pessoa”)]
public int PessoaID { get; set;
}
[Required(ErrorMessage =
“Campo Nome: preenchimento
obrigatório”)]
[StringLength(10,
ErrorMessage=”Campo Nome:
máximo de 10 caracteres.”)]
public string Nome { get; set;
Figura 9. Validações no ASP.NET MVC
}
[Required(ErrorMessage = “Campo
Nascimento: preenchimento
obrigatório”)]
public DateTime Nascimento {
get; set; }
Note que além da obrigatoriedade dos campos, adicionamos uma validação onde o campo Nome, deve conter até 10 caracteres. Fica mais fácil marcar a
propriedade com DataAnnotations, do que comparar cada campo no Controller.
Rode a aplicação e tente cadastrar um registro com o nome em branco
ou que a quantidade de caracteres do Nome seja maior que 10 (Figura 9).
Veja a figura 9
Conclusões
Sobre o autor
Luciano Pimenta
Luciano Pimenta (NOVO DOMINIO: www.lucianopimenta.com) é desenvolvedor Delphi/C#
para aplicações Web com ASP.NET, Windows com Win32 e Windows Forms com .NET. Palestrante
da 4ª edição da Borland Conference (BorCon) e da 1ª Delphi Conference.
É MVP Embarcadero, grupo de profissionais que ajudam a divulgar o Delphi no mundo.
Atualmente é desenvolvedor da SoftDesign fábrica de softwares em Porto Alegre-RS.
Autor de mais de 90 artigos e de mais de 600 vídeos aulas publicadas em revistas e sites
especializados, além de treinamentos presenciais e multimídias. É consultor da FP2 Tecnologia
(www.fp2.com.br) onde ministra cursos de programação e banco de dados.
www.lucianopimenta.net
Vimos neste artigo os primeiros passos para desenvolver projetos Web
usando o ASP.NET MVC. No próximo artigo, veremos mais dicas e como trabalhar com banco de dados usando o Entity Framework. Um grande abraço
a todos e até a próxima!
dezembro
2013
25
dicas the club
Dicas Delphi
Dica 1 - Dividir Linhas de um Texto (.Txt) no TMemo
Em algumas aplicações existe a necessidade de manipularmos textos ou
dados que estejam gravados em blocos de Strings, portanto, vamos demonstrar
uma forma simples de trabalharmos com este tipo de funcionalidade.
Utilizaremos um arquivo de texto (.txt) no qual temos valores numéricos e
iremos dividir estes valores em outros arquivos de acordo com as informações
que o usuário indicar. O formulário deve ficar parecido com imagem 1.
Para facilitar a visualização vamos apresentar os dados em 2 Memos,
o primeiro (Esquerda) irá apresentar os dados iniciais, ou seja, aqueles que
serão manipulados, já em nosso segundo Memo serão apresentados os dados
em execução.
Vamos iniciar com o comando do botão ‘Carregar’ que irá listar os dados
originais em nosso primeiro Memo, veja a codificação abaixo:
Listagem 1 – Botão Carregar.
procedure TForm1.
Button1Click(Sender: TObject);
begin
Memo1.Clear;
Memo2.Clear;
Memo1.Lines.
LoadFromFile(‘lista.txt’);
Edit1.Text := IntToStr(Memo1.
Lines.Count);
end;
Após carregarmos os dados podemos começar a manipulação, veja que
temos um ‘Edit’ intitulado de ‘Dividir’ nele iremos inserir a quantidade de
linhas que que indicará de quantas em quantas linhas o texto será dividido. Para
evitar erros de digitação insira no evento ‘OnKeyPress’ o seguinte comando:
Listagem 2 – Evento KeyPress.
Imagem 1 – Formulário Principal.
26
dezembro
2013
procedure TForm1.
edtDividirKeyPress(Sender:
TObject; var Key: Char);
begin
if not (key in [‘0’..’9’,
#08]) then
key := #0;
end;
Assim nosso campo irá apenas aceitar valores numéricos. Outra restrição
que podemos indicar é para que o valor inserido no campo ‘Dividir’ não seja
maior que o total de linhas de nosso arquivo, para isto vamos utilizar o evento
‘OnExit’ do Edit, veja listagem abaixo:
Listagem 3 – Evento OnExit.
procedure TForm1.
edtDividirExit(Sender:
TObject);
var
Total, Dividir: Integer;
begin
if edtTotal.Text <> ‘’ then
Total := StrToInt(edtTotal.
Text);
if edtDividir.Text <> ‘’ then
Dividir :=
StrToInt(edtDividir.Text);
if Total < Dividir then
begin
ShowMessage(‘Total de
Linhas é Menor que o Divisor’);
edtDividir.SetFocus;
end;
end;
StrToInt(edtDividir.Text),
Memo2);
Total := StrToInt(edtTotal.
Text);
Dividir :=
StrToInt(edtDividir.Text);
Calculado := Total Dividir;
edtTotal.Text :=
IntToStr(Calculado);
Memo2.Lines.SaveToFile(E
xtractFilePath(Application.
ExeName) + ‘Texto’ + edtTotal.
Text + ‘.txt’);
Memo2.Lines.Clear;
until Dividir > Total Dividir;
Memo1.Lines.SaveToFile(Extrac
tFilePath(Application.ExeName)
+ ‘Resto.txt’);
Memo1.Lines.Clear;
end;
Foi criado um arquivo com 1000 números chamado ‘lista.txt’, ao executar
o divisor em 300 linhas foram gerados os arquivos conforme imagem abaixo:
Por fim iremos executar o comando de nosso botão ‘Dividir’ que irá separar
os dados e salvar em lotes dependendo do valor passado pelo usuário, abaixo
a listagem do botão ‘Dividir’:
Listagem 4 – Botão Dividir.
procedure TForm1.
btnDividirClick(Sender:
TObject);
var
Total, Dividir, Calculado:
Integer;
begin
repeat
SepararLinhas(Memo1,
Imagem 2 – Arquivos Gerados.
Veja que os arquivos foram nomeados de acordo com o restante de linhas
que nosso arquivo original possuía.
Esta dica pode ser implementada e melhorada de acordo com as necessidades do usuário.
Espero que tenham gostado e até a próxima.
dezembro
2013
27
Dica 2 – Contar Registros do Banco de Dados
Nesta dica vamos demonstrar uma forma simples para contar quantas
vezes um determinado valor aparece dentro de uma tabela, ou seja, um ‘SELECT
COUNT’, mas de forma dinâmica utilizando o Delphi.
Para esta funcionalidade vamos utilizar um modelo simples de conexão
com os componentes:
•
•
•
•
•
SQLConnection;
SQLDataSet;
DataSetProvide;
ClientDataSet;
DataSource.
Vamos utilizar também um ‘SQLQuery’ para executar nossas consultas .
O formulário irá ficar conforma imagem abaixo:
que seja o campo ‘Parcela’.
Antes de prosseguirmos insira as listagens abaixo para que a aplicação
execute corretamente:
Listagem 1 – Evento OnShow.
procedure TForm1.
FormShow(Sender: TObject);
begin
ClientDataSet1.Open;
end;
Listagem 2 – Evento OnClose.
procedure TForm1.
FormClose(Sender: TObject; var
Action: TCloseAction);
begin
ClientDataSet1.Close;
end;
Listagem 3 – Evento SQLConnection (BeforeConnect).
procedure TForm1.SQLConnection1
BeforeConnect(Sender: TObject);
begin
SQLConnection1.
LoadParamsFromIniFile(‘Connect.
ini’);
end;
Após definir as ‘Tags’ para cada ‘Edit’ vamos iniciar a codificação do botão
‘Contar’ veja na listagem abaixo:
Listagem 4 – Botão Contar.
Imagem 1 – Formulário Principal.
Veja que temos 2 ‘Labels’ que seriam os apelidos de nossos campos,
temos também logo a frente ‘(Tag = X)’ o que significa que o bloco de ‘Edits’
abaixo receberá em sua propriedade ‘Tag’ o valor que está indicado, portanto,
marque ‘Tag = 1’ no campo que deseja indicar o campo ‘Valor’ e ‘Tag = 2’ para
28
dezembro
2013
Procedure TForm1.
btnContarClick(Sender:
TObject);
var
Campo: String;
I, R: Integer;
C: TComponent;
begin
for I := 0 to ComponentCount
- 1 do
begin
C := Components[I];
if (C is TEdit) and
(TEdit(C).Text <> ‘’) then
begin
SQLQuery1.Close;
// Pode passar seus
campos de forma Dinâmica
case TEdit(C).Tag of
1: begin
Campo := ‘VALOR’;
SQLQuery1.SQL.Text
:= ‘SELECT COUNT(‘ + Campo + ‘)
FROM NUMEROS WHERE ‘ + Campo +
‘ = :V’;
SQLQuery1.Params.
ParamByName(‘V’).Value :=
TEdit(C).Text;
SQLQuery1.Open;
R := SQLQuery1.
Fields[0].AsInteger;
ShowMessage(‘Valor
(‘ + TEdit(C).Text + ‘) = ‘ +
IntToStr(R));
end;
2: begin
Campo := ‘PARCELA’;
SQLQuery1.SQL.Text
:= ‘SELECT COUNT(‘ + Campo + ‘)
FROM NUMEROS WHERE ‘ + Campo +
‘ = :V’;
SQLQuery1.Params.
ParamByName(‘V’).Value :=
TEdit(C).Text;
SQLQuery1.Open;
R := SQLQuery1.
Fields[0].AsInteger;
ShowMessage(‘Parcela
(‘ + TEdit(C).Text + ‘) = ‘ +
IntToStr(R));
end;
end;
end;
end;
end;
‘Campo’, veja que dentro de nossa instrução concatenamos a variável ‘Campo’
para que possamos consultar de acordo com o valor passado, por fim nossa
variável ‘R’ irá receber o total de registros encontrados para que possamos
exibir na tela o valor final, veja na imagem 2:
Imagem 2 – Resultado da Contagem.
Esta dica pode ser implementada e melhorada de acordo com as necessidades, Espero que tenham gostado e até a próxima.
Para tornar a contagem dinâmica vamos utilizar uma variável do tipo
‘TComponent’ assim utilizando o comando ‘if (C is TEdit) and (TEdit(C).Text
<> ‘’) then’ iremos apenas executar nossa instrução se o componente for um
‘TEdit’. Dentro do ‘Case’ iniciamos passando o valor de nosso campo a variável
dezembro
2013
29
desafio the club
Questões
1 - A função AnsiIndexStr utilizada para fornecer o índice de uma matriz de strings pertence a Unit ...
2 - Base para componentes que apresentam informações em uma grade bidimensional.
3 - Procedimento responsável por remover todos os registros de um DataSet.
4 - Procedimento responsável por gravar atualizações pendentes no banco de dados.
5 - Função utilizada para alterar o nome de um arquivo.
6 - Função que retorna data e hora atual.
7 - Caractere usado para separar a parte inteira da fracionária de um número.
8 - Função que retorna uma SubString de uma String ou Segmento de uma Matriz.
9 - Função que retorna o índice do primeiro caractere de uma substring especificada.
10- O procedimento Free responsável por limpar um objeto da memória pertence a Unit ...
30
dezembro
2013
dezembro
2013
05
dezembro
2013
Download

Dicas Delphi