the club - megazinetipos de linguagens e ferramentas de desenvolvimento. nosso consultor técnico...

32
junho 2014

Upload: others

Post on 11-Jul-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014

Page 2: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014

Page 3: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 03

20

Índice

Editorial

04

16

Autor: Lucas Vieira de Oliveira

05

Autor: João Marcos Sakalauska

25Android - Criando Abas com TabHost e TabSpec

Autor: Thiago C. Montebugnoli

Autor: Jeferson Silva de Lima

ASP.NET

Delphi - Criando uma classe para ordenação de DBGrids

Delphi XE5 – Sincronização de Dados

Aplicações .NET em camadas, teoria e prática - Parte 4

Page 4: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201404

Delphi é marca registrada da Borland International, as demais marcas citadas são registradas

pelos seus respectivos proprietários.

Thiago Montebugnoli - Editor [email protected]

Olá amigos do The Club!

É sempre com muita satisfação que apresento mais uma edição de nossa revista. Procuramos abranger todo público envolvendo diversos tipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica para Ordenação de dados em DBGrids. Esta dica se torna muito útil pois nos auxilia na visualização dos dados, os apresentando de forma pré-ordenada. Já nosso outro consultor técnico Jeferson Silva de Lima, continua explorando os recursos do Delphi XE com o artigo “Delphi XE5 - Sincronização de Dados”. Neste mês ele prossegue com o desenvol-vimento utilizando o Android, demonstrando como sincronizar os dados do dispositivo móvel com o Banco de Dados localizados no Servidor. João Marcos Sakalausca, nosso colaborador mensal, finaliza o artigo “Aplicações NET em camadas, teoria e prática - Parte 4” e disponibiliza para download o exemplo completo envolvendo todas as teorias abordadas ao longo destes quatro artigos. Para finalizar, continuo minha saga redigindo artigos sobre Android, tendo como base o Eclipse. Procuro sempre envolver artigos fáceis e práticos ao longo deste período, e neste mês não foi diferente, criei um exemplo prático com as classes “TabHost” e “TabSpec”, ambas necessárias para implementação de abas nos sistemas móveis, um recurso que tornará os aplicativos visualmente melhores organizados.

Um Abraço a todos e muita sorte para nossa seleção nesta copa do mundo.

Av. Profº Celso Ferreira da Silva, 190 Jd. Europa - Avaré - SP - CEP 18.707-150

Informações e Suporte: (14) 3732-1529

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected] Informações: [email protected] Cadastro: theclub_cadastro

Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3

www.twitter.com/theclubbr

Copyright The Club 2013

Diretor TécnicoMarcos César Silva

DiagramaçãoVitor M. Rodrigues

DesignVitor M. Rodrigues

RevisãoDenise Blair

ColunistasHamden Vogel

Jeferson Silva de LimaLuciano Pimenta

Lucas Vieira de OliveiraThiago Cavalheiro Montebugnoli

Impressão e acabamento:GRIL - Gráfica e Editora

Taquarituba-SP - Tel. (14) 3762-1345

ReproduçãoA 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.

Editorial

Page 5: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 05

Listagem 01No artigo anterior, foi tratado a parte final da implementa-ção da aplicação, mas pela extensão do artigo o mesmo precisou ser dividido em duas partes. No artigo anterior, foi alterado a View referente à listagem de usuários (Lista-rUsuarios) e aproveitamos para criar a View para inserção

do novo usuário (CriarUsuario), visualizando esse novo cadastro na listagem logo após a inserção.

Nesse artigo, o foco será a alteração, detalhe e exclusão.

Então, para começar, vamos implementar as funcionalidades referente às ações (Actions) relacionadas à nossa viewListarUsuarios, como mostra a imagem 01.

Imagem 01 – Ações referentes à Listagem de Usuários.

Abra a classe UsuarioController e crie as Actions: EditarUsuario, Deta-lheUsuario, DeletarUsuario. Inicialmente ela ficará com a seguinte estrutura:

publicActionResult EditarUsuario(){return View();}

publicActionResult DetalheUsuario(){return View();}

publicActionResult DeletarUsuario(){return View();}

Com a estrutura de Actions criada no Controller, teremos que criar as Views “tipadas” que possam atender as solicitações que forem passadas para o Controller.

Para isso, clique com o botão direito do mouse em cima da pasta “Usuario” e vá até a opção Add ->View como mostra a imagem 02.

Imagem 02 – Adicionando as views

Aplicações NET em camadas, teoria e prática - Parte 4

Page 6: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201406

Listagem 02

Na tela “AddView” renomeie “ViewName” para EditarUsuario, em seguida, clique na opção “Create a strongly-typedview” e em “View Data Class” selecione MvcApp.Usuario, para finalizar Selecione a opção “Edit” em “ViewContent” como mostra a imagem 03.

Imagem 03 – ViewEditarUsuario

Repita a etapa para adicionar a View (mostrado na imagem 02) clicando com o botão direito do mouse na pasta “Usuario” e navegando até a opção Add ->View.

Na tela “AddView” renomeie “ViewName” para DetalheUsuario, em seguida, clique na opção “Create a strongly-typedview” e em “View Data Class” selecione MvcApp.Usuario, para finalizar Selecione a opção “Details” em “ViewContent” como mostra a imagem 04.

Imagem 04 – ViewDetalheUsuario

Repita a etapa para adicionar a View (mostrado na imagem 02) clicando com o botão direito do mouse na pasta “Usuario” e navegando até a opção Add ->View.

Na tela “AddView” renomeie “ViewName” para DeletarUsuario, em seguida, clique na opção “Create a strongly-typedview” e em “View Data Class” selecione MvcApp.Usuario, para finalizar Selecione a opção “Delete” em “ViewContent” como mostra a imagem 05.

Imagem 05 – ViewDeletarUsuario

Salve o projeto e teste o que foi implementado acessando a aplicação. Se tudo estiver de acordo com o que foi implementado, a viewEditarUsuario estará da seguinte forma:

<%@PageTitle=””Language=”C#”MasterPageFile=”~/Views/Shared/Site.Master”Inherits=”System.Web.Mvc.ViewPage<MvcApp.Usuario>”%>

<asp:ContentID=”Content1”ContentPlaceHolderID=”TitleContent”runat=”server”> EditarUsuario</asp:Content>

<asp:ContentID=”Content2”ContentPlaceHolderID=”MainContent”runat=”server”>

<h2>EditarUsuario</h2>

<%using (Html.BeginForm()) {%><%:Html.ValidationSummary(true) %>

Page 7: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 07

<fieldset><legend>Fields</legend>

<divclass=”editor-label”><%:Html.LabelFor(model =>model.IdUsuario) %></div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.IdUsuario) %><%:Html.ValidationMessageFor(model =>model.IdUsuario) %></div>

<divclass=”editor-label”><%:Html.LabelFor(model =>model.NomeUsuario) %></div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.NomeUsuario) %><%:Html.ValidationMessageFor(model =>model.NomeUsuario) %></div>

<divclass=”editor-label”><%:Html.LabelFor(model =>model.EmailUsuario) %></div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.EmailUsuario) %><%:Html.ValidationMessageFor(model =>model.EmailUsuario) %></div>

<divclass=”editor-label”><%:Html.LabelFor(model =>model.Login) %></div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.Login) %><%:Html.ValidationMessageFor(model =>model.Login) %></div>

<divclass=”editor-label”><%:Html.LabelFor(model =>model.

Senha) %></div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.Senha) %><%:Html.ValidationMessageFor(model =>model.Senha) %></div>

<p><inputtype=”submit”value=”Save”/></p></fieldset>

<% } %>

<div><%:Html.ActionLink(“Back to List”, “Index”) %></div>

</asp:Content>

E será apresentada como mostra a imagem 06.

Imagem 06 – ViewEditarUsuario

Page 8: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201408

Listagem 03

Agora, modificaremos a View EditarUsuario, em seguida o Controller e posteriormente o Model para que ela atenda aos requisitos por completo. Para que a View fique da forma que esperamos utilize o seguinte código:

<%@PageTitle=””Language=”C#”MasterPageFile=”~/Views/Shared/Site.Master”Inherits=”System.Web.Mvc.ViewPage<MvcApp.Usuario>”%>

<asp:ContentID=”Content1”ContentPlaceHolderID=”TitleContent”runat=”server”> EditarUsuario</asp:Content>

<asp:ContentID=”Content2”ContentPlaceHolderID=”MainContent”runat=”server”>

<h2>Editar Usuário</h2>

<%using (Html.BeginForm(“SalvarUsuarioEditado”, “Usuario”)){%><%:Html.ValidationSummary(true)%>

<fieldset><legend>Campos</legend>

<divclass=”editor-label”> ID:</div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.IdUsuario)%><%:Html.ValidationMessageFor(model =>model.IdUsuario)%></div>

<divclass=”editor-label”> Nome:</div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.NomeUsuario)%><%:Html.ValidationMessageFor(model =>model.NomeUsuario)%></div>

<divclass=”editor-label”> E-mail:</div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.EmailUsuario)%><%:Html.ValidationMessageFor(model =>model.EmailUsuario)%></div>

<divclass=”editor-label”>Login:</div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.Login)%><%:Html.ValidationMessageFor(model =>model.Login)%></div>

<divclass=”editor-label”>Senha:</div><divclass=”editor-field”><%:Html.TextBoxFor(model =>model.Senha)%><%:Html.ValidationMessageFor(model =>model.Senha)%></div>

<p><inputtype=”submit”value=”Salvar”/></p></fieldset>

<% }%>

<div><%:Html.ActionLink(“Voltar para a Listagem de Usuários”, “ListarUsuarios”) %></div>

</asp:Content>

Salve o projeto e teste a aplicação, nesse caso, a View deverá estar seme-lhante à estrutura apresentada na imagem 07.

Page 9: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 09

Listagem 04

Listagem 05

Listagem 06

Imagem 07 – Estrutura da View após edição.

Agora, passaremos para nosso Model e Controller, para implementar os métodos que carregarão os dados para edição.

No Controller UsuarioController, nosso código deverá ficar da seguinte forma:

publicActionResultEditarUsuario(int id){return View(mUsuario.Selecionar(id));}

[HttpPost]publicActionResult SalvarUsuarioEditado(){longidUsuario = 0;

u.IdUsuario = Convert.ToUInt32 ( Request[“IdUsuario”].ToString() );

u.NomeUsuario = Request [“NomeUsuario”].ToString();u.EmailUsuario = Request [“EmailUsuario”].ToString();u.Login = Request[“Login”].ToString();u.Senha = Request[“Senha”].ToString();idUsuario = mUsuario.Atualizar(u);

returnRedirectToAction(“ListarUsuarios”);}

No Model, deverá ficar da seguinte forma:

Antes:

///<summary>/// Seleciona as informações de um usuário específico pela entidade Usuário passada através de Info.///</summary>///<param name=”info”></param>///<returns></returns>publicList<Usuario> Selecionar(Usuario info){ context = newMVC();

IQueryable<Usuario> selecionarUsuario = context.Usuario.AsQueryable<Usuario>();selecionarUsuario = selecionarUsuario.Where(u =>u.IdUsuario == info.IdUsuario);returnselecionarUsuario.ToList();}

Depois:

///<summary>/// Seleciona as informações de um usuário específico pela entidade Usuário passada através de Info.///</summary>///<param name=”info”></param>

Page 10: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201410

Listagem 07

Listagem 08

///<returns></returns>publicUsuarioSelecionar(int id){context = newMVC();Usuariousuario = newUsuario();IQueryable<Usuario>selecionarUsuario = context.Usuario.AsQueryable<Usuario>().Where(u =>u.IdUsuario == id); foreach (var item inselecionarUsuario) {usuario.IdUsuario = item.IdUsuario;usuario.NomeUsuario = item.NomeUsuario;usuario.EmailUsuario = item.EmailUsuario;usuario.Login = item.Login;usuario.Senha = item.Senha;}returnusuario;}

Novo método incluso:

///<summary>/// Atualiza as informações da entidade Usuário passada através de Info.///</summary>///<param name=”info”>Informações da Entidade Usuário</param>///<returns>Id do Usuário cadastrado</returns>publiclongAtualizar(Usuario info){

using (context = newMVC()){Usuariousuario = newUsuario();usuario = context.Usuario.First<Usuario>(u =>u.IdUsuario == info.IdUsuario);usuario.IdUsuario = info.IdUsuario;usuario.NomeUsuario = info.NomeUsuario;usuario.EmailUsuario = info.EmailUsuario;usuario.Login = info.Login;usuario.Senha = info.Senha;

context.SaveChanges();

return info.IdUsuario; }}

Salve o projeto, rode a aplicação, execute a edição, o resultado deverá ser o mesmo das imagens 08 e 09.

Antes da Alteração:

Imagem 08 – Antes da alteração

Depois da alteração:

Imagem 09 – Depois da alteração

Com o método “Editar” pronto, vamos passar para o método “Detalhes”.

Atualmente a View criada possui o seguinte código:

<%@PageTitle=””Language=”C#”MasterPageFile=”~/Views/Shared/Site.Master”Inherits=”System.Web.Mvc.ViewPage<MvcApp.Usuario>”%>

<asp:ContentID=”Content1”ContentPlaceHolderID=”TitleContent”runat=”server”> DetalheUsuario</asp:Content>

<asp:ContentID=”Content2”ContentPlaceHolderID=”MainContent”run

Page 11: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 11

Listagem 09

Listagem 10

at=”server”>

<h2>DetalheUsuario</h2>

<fieldset><legend>Fields</legend>

<divclass=”display-label”>IdUsuario</div><divclass=”display-field”><%:Model.IdUsuario%></div>

<divclass=”display-label”>NomeUsuario</div><divclass=”display-field”><%:Model.NomeUsuario%></div>

<divclass=”display-label”>EmailUsuario</div><divclass=”display-field”><%:Model.EmailUsuario%></div>

<divclass=”display-label”>Login</div><divclass=”display-field”><%:Model.Login%></div>

<divclass=”display-label”>Senha</div><divclass=”display-field”><%:Model.Senha%></div>

</fieldset><p>

<%:Html.ActionLink(“Edit”, “Edit”, new { id=Model.IdUsuario }) %> |<%:Html.ActionLink(“Back to List”, “Index”) %></p>

</asp:Content>

Se rodássemos nesse momento não teríamos sucesso, pois, ela é uma View tipada que não possui objeto ou referência de objeto sendo passada pelo Controller através da Action DetalheUsuario().

Para deixarmos funcionando, será necessário fazer algo semelhante ao que fizemos no método EditarUsuario. Sendo assim, altere o código da actionDetalheUsuario():

Antes:

publicActionResult DetalheUsuario(){return View();}

Depois

publicActionResultDetalheUsuario(int id){return View(mUsuario.Selecionar(id));}

O resultado dessa pequena alteração será a estrutura mostrada na imagem 10.

Imagem 10 – ViewDetalheUsuario

Para finalizar, vamos alterar o layout da view para que fique mais agradável e compreensivo, para isso, basta usar o código a seguir:

Page 12: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201412

Listagem 11

Listagem 12

Listagem 13

<%@PageTitle=””Language=”C#”MasterPageFile=”~/Views/Shared/Site.Master”Inherits=”System.Web.Mvc.ViewPage<MvcApp.Usuario>”%>

<asp:ContentID=”Content1”ContentPlaceHolderID=”TitleContent”runat=”server”> DetalheUsuario</asp:Content>

<asp:ContentID=”Content2”ContentPlaceHolderID=”MainContent”runat=”server”>

<h2>Detalhes do Usuário</h2>

<fieldset><legend>Campos</legend>

<divclass=”display-field”><strong>ID: </strong><%:Model.IdUsuario%></div><divclass=”display-field”><strong>Nome: </strong><%:Model.NomeUsuario%></div><divclass=”display-field”><strong>E-mail: </strong><%:Model.EmailUsuario%></div><divclass=”display-field”><strong>Login: </strong><%:Model.Login%></div><divclass=”display-field”><strong>Senha: </strong><%:Model.Senha%></div>

</fieldset><p><%:Html.ActionLink(“Editar”, “EditarUsuario”, new { id = Model.IdUsuario })%> |<%:Html.ActionLink(“Voltar para a Listagem de Usuários”, “ListarUsuarios”)%></p>

</asp:Content>

O resultado dessa alteração será o mesmo da imagem 11.

Imagem 11 – ViewDetalheUsuario finalizada.

Por último, vamos implementar o método Deletar.

Semelhante ao caso do método Detalhe, não podemos acessa-lo logo de cara, pois, apresentaria erro.

Então, será necessário mexer no Controller primeiro para dar sequencia a implementação.

Antes:

publicActionResult DeletarUsuario(){return View();}

Depois

publicActionResult DeletarUsuario(int id){return View (mUsuario.Selecionar(id));}

Atualmente, o código apresenta a seguinte estrutura:

Page 13: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 13

Listagem 14

Listagem 15

<%@PageTitle=””Language=”C#”MasterPageFile=”~/Views/Shared/Site.Master”Inherits=”System.Web.Mvc.ViewPage<MvcApp.Usuario>”%>

<asp:ContentID=”Content1”ContentPlaceHolderID=”TitleContent”runat=”server”> DeletarUsuario</asp:Content>

<asp:ContentID=”Content2”ContentPlaceHolderID=”MainContent”runat=”server”>

<h2>DeletarUsuario</h2>

<h3>Are you sure you want to delete this?</h3><fieldset><legend>Fields</legend>

<divclass=”display-label”>IdUsuario</div><divclass=”display-field”><%:Model.IdUsuario%></div>

<divclass=”display-label”>NomeUsuario</div><divclass=”display-field”><%:Model.NomeUsuario%></div>

<divclass=”display-label”>EmailUsuario</div><divclass=”display-field”><%:Model.EmailUsuario%></div>

<divclass=”display-label”>Login</div><divclass=”display-field”><%:Model.Login%></div>

<divclass=”display-label”>Senha</div><divclass=”display-field”><%:Model.Senha%></div>

</fieldset><%using (Html.BeginForm()) { %><p> <inputtype=”submit”value

=”Delete”/> | <%:Html.ActionLink(“Back to List”, “Index”) %></p><% }%>

</asp:Content>

Se rodarmos a aplicação nesse momento, será apresentada a seguinte tela, como mostra a imagem 12.

Imagem 12 – Tela referente àViewDeletarUsuario

Nesse momento, basta alterar o Model e o Controller para em seguida alterar a View deixando o layout de forma agradável e compreensível.

No Model UsuarioModels, insira o seguinte método:

///<summary>/// Deleta as informações da entidade Usuário passada através de Info.///</summary>///<param name=”info”>Informações da

Page 14: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201414

Listagem 17

Listagem 16

Entidade Usuário</param>publicvoidDeletar(Usuario info){using (context = newMVC()) {Usuariousuario = newUsuario();usuario = context.Usuario.First<Usuario>(u =>u.IdUsuario == info.IdUsuario);context.DeleteObject(usuario);context.SaveChanges();}}

No Controller, insira a seguinte Action:

[HttpPost]publicActionResultDeletarUsuarioSelecionado(int id){u.IdUsuario = id;mUsuario.Deletar(u);returnRedirectToAction(“ListarUsuarios”);}

Na View, deixe o código com a seguinte estrutura:

<%@PageTitle=””Language=”C#”MasterPageFile=”~/Views/Shared/Site.Master”Inherits=”System.Web.Mvc.ViewPage<MvcApp.Usuario>”%>

<asp:ContentID=”Content1”ContentPlaceHolderID=”TitleContent”runat=”server”> DeletarUsuario</asp:Content>

<asp:ContentID=”Content2”ContentPlaceHolderID=”MainContent”runat=”server”>

<h2>Deletar Usuário</h2>

<h3>Deseja deletar o usuário a seguir?</h3><fieldset><legend>Campos</legend>

<divclass=”display-field”><strong>ID: </strong><%:Model.IdUsuario%></

div><divclass=”display-field”><strong>Nome: </strong><%:Model.NomeUsuario%></div><divclass=”display-field”><strong>E-mail: </strong><%:Model.EmailUsuario%></div><divclass=”display-field”><strong>Login: </strong><%:Model.Login%></div><divclass=”display-field”><strong>Senha: </strong><%:Model.Senha%></div>

</fieldset><%using (Html.BeginForm(“DeletarUsuarioSelecionado”, “Usuario”, new { id = Model.IdUsuario })) { %><p> <inputtype=”submit”value=”Deletar”/> | <%:Html.ActionLink(“Voltar para a Listagem de Usuários”, “ListarUsuarios”)%></p><% }%>

</asp:Content>

Dessa forma, a View atenderá a funcionalidade proposta como mostra às imagens 13, 14, 15;

Antes da Exclusão: Veja a Imagem 13.

Apresentando os dados do registro que será Excluído:

Imagem 14 – Registro selecionado para Exclusão

Page 15: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 15

Imagem 15 – Listagem após a Exclusão

E essa é nossa aplicação MVC, contendo o CRUD de Usuários (CReate, Update, Delete).

Conclusão

Nesse artigo finalizamos a aplicação de forma que poderá ser usada como base para que evoluções sejam feitas a partir dela ou de novos projetos.

Lembrando que o conjunto de artigos contempla apenas um CRUD em cima do Framework MVC do .NET Framework.

Muita coisa pode ser melhorada inclusive por conta de versões mais atuais, mas de qualquer forma, espero ter ajudado aqueles que não tinham nenhuma conhecimento a respeito de MVC no .NET Framework.

Imagem 13 – Listagem antes da Exclusão

[email protected]

João Marcos Sakalauska31 anos, é Analista de Sistemas e atua a mais de 10 anos na área de TI. Sócio proprietário na empresa IT Solution (http://www.itsolution.com.

br/), prestando serviços de consultoria atuando como Analista de Sistemas em projetos que utilizam as tecnologias VB6, .NET e Sql Server.

Sobre o autor

Page 16: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201416

Listagem 1 - Função Sincronizar.

Introdução

Neste artigo vamos dar continuidade no desenvolvimento com Android, portanto, demonstraremos uma forma de sincronizar os dados de seu dispo-sitivo móvel com seu banco de dados no servidor.

Aplicação

Para prosseguirmos com o projeto utilizaremos como base a aplicação criada anteriormente, ou seja, nossa aplicação DataSnap. Caso haja dúvidas sobre a criação consulte os artigos ‘ Delphi XE5 – Primeiros Passos ’ e ‘ Delphi XE5 – Trabalhando com Métodos no Android ’.

Servidor

Inicialmente vamos acessar nosso servidor DataSnap e criaremos a função responsável por enviar os dados de nosso banco de dados para o Cliente(Android). Portanto, crie a seguinte função:

Function Sincronizar(Tabela: String; var SQL: String): Boolean;Var I: Integer; Aux, S: String; ListaSQL: TStringList;begin Try Aux:= EmptyStr; S:= EmptyStr; ListaSQL:= TStringList.

Create; Case AnsiIndexStr(Tabela,[‘PRODUTOS’]) of 0:Begin //Produtos cdsProdutos.Close; cdsProdutos.Open;FormatSettings.DecimalSeparator:= ‘.’; While not cdsProdutos.Eof do Begin Aux:= IntToStr(cdsProdutosID_PRODUTO.AsInteger) + ‘, ‘;

if not (cdsProdutosPRODUTO.IsNull) then Aux:= Aux + QuotedStr(cdsProdutosPRODUTO.AsString) + ‘, ‘ else Aux:= Aux + ‘Null,’; if not (cdsProdutosVALOR_UN.IsNull) then Aux:= Aux + FloatToStr(cdsProdutosVALOR_UN.AsFloat) else Aux:= Aux + ‘Null’;

Delphi XE5 – Sincronização de Dados

Page 17: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 17

Listagem 2 – Botão Sincronizar.

S:= ‘INSERT INTO PRODUTOS (ID_PRODUTO,PRODUTO,VALOR_UN) VALUES (‘+ Aux +’);’; Aux:= ‘’; ListaSQL.Add(S); S:= ‘’; cdsProdutos.Next; End; for I := 0 to ListaSQL.Count-1 do Begin SQL:= SQL + ListaSQL.Strings[I]; End; Result:= True; cdsProdutos.Close; FormatSettings.DecimalSeparator:= ‘,’; End; End; Except on E: Exception do Result:= False; end; ListaSQL.Free;end;

Ao utilizarmos a função ‘ AnsiIndexStr ’ deixamos espaço para a sincro-nização de outras tabelas de formas simples, ou seja, com a inserção de um novo índice ‘ String ’ na função e um novo índice no Case podemos acessar os dados de outras tabelas caso seja necessário.

Cliente

Após configurarmos o servidor vamos para nossa aplicação Cliente (Android). Adicione um botão na tela inicial e nomeie de ‘ btnSincronizar ’ adicione também um componente ‘ AniIndicator ’ e deixe a propriedade ‘ Visible ’ como False.

Imagem 1 – Tela Inicial.

Feito isso vamos ao evento ‘ OnClick ’ do botão Sincronizar e adicione o comando de sincronização, veja abaixo:

procedure btnSincronizarClick(Sender: TObject);Var S, Tabela: String; Lista: TStringList; B: Boolean; I, J: Integer;begin if MessageDlg(‘Deseja Sincronizar os Dados? Processo pode levar alguns Minutos!’, TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0) = mrYes then begin btnPedido.Visible:= False; AniIndicator1.Visible:= True; AniIndicator1.Enabled:= True; Application.ProcessMessages; Try Lista:= TStringList.Create; Lista.Add(‘PRODUTOS’); for I := 0 to Lista.Count-1 do Begin Tabela:= Lista.Strings[I]; DM.Metodos.ServerMethodName:= ‘TServerMethods1.Sincronizar’; DM.Metodos.ParamByName(‘Tabela’).AsString:= Tabela; DM.Metodos.ExecuteMethod; B:= DM.Metodos.ParamByName(‘ReturnParameter’).AsBoolean; if B = True then begin DM.sdsAuxiliar.close; DM.sdsAuxiliar.CommandText := ‘DELETE FROM ‘ + Tabela;

Page 18: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201418

Listagem 3 – Função ContarCaracter.

Listagem 4 – Função LerSQL.

DM.sdsAuxiliar.ExecSQL;

DM.sdsAuxiliar.close; DM.sdsAuxiliar.CommandText := ‘SELECT * FROM ‘ + Tabela; DM.sdsAuxiliar.ExecSQL;

if DM.sdsAuxiliar.RecordCount = 0 then Begin S:= DM.Metodos.ParamByName(‘SQL’).AsString; for J := 0 to ContarCaracter(S) - 1 do Begin DM.sdsAuxiliar.Close; DM.sdsAuxiliar.CommandText:= LerSQL(S,J); DM.sdsAuxiliar.ExecSQL; Application.ProcessMessages; End; End; End else ShowMessage(‘ Falha na Tabela (‘+ Tabela +’).’); end; ShowMessage(‘Sincronização Finalizada com Sucesso!’); Except on E: Exception do ShowMessage(‘Falha ao Sincronizar!’+E.Message); end; Lista.Free; btnPedido.Visible:= True; AniIndicator1.Enabled:= False; AniIndicator1.Visible:= False; Application.ProcessMessages; end;end;

Neste processo criamos uma variável ‘ Lista ’ do tipo TStringList para arma-zenarmos o nome das tabelas que desejamos sincronizar, lembre-se os nomes

devem ser os mesmos que indicamos em nosso servidor, ou seja, nossa tabela de Produtos. Veja que antes de executar a inserção apagamos qualquer registro que esteja na base do dispositivo móvel para evitarmos dados duplicados.

Para a execução deste processo utilizamos 2 funções para nos auxiliar, abaixo segue a sintaxe delas e suas respectivas funções.

function ContarCaracter(C: String): Integer;Var I, Qtd: Integer;begin Qtd:= 0; for I := 1 to Length(C) do Begin if C[I] = ‘;’ then Qtd:= Qtd +1; End; Result:= Qtd;end;

Esta função foi utilizada para contar a quantidade de vezes que o carac-tere ‘ ; ’ aparece em nossa ‘ String ’, utilizaremos este valor para definirmos a quantidade de ‘ Inserts ’ que serão aplicados em nosso banco de dados. Nossa próxima função complementa a utilização da ’ContarCaracter’, ou seja, com o valor indicado em nosso ‘For’ vamos criar o laço de repetição até que todos os registros sejam inseridos.

function LerSQL(SQL: String; Linha: Integer): String;Var S: string; I: Integer;begin for I := 0 to Linha - 1 do begin Delete(SQL, 1, Pos(‘;’, SQL)); end; S := Copy(SQL, 1, Pos(‘;’, SQL) - 1); Result := S;end;

Após isso basta compilarmos para visualizarmos os dados em sincroni-zação.

Page 19: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 19

Imagem 2 – Sincronizando.

Conclusão

Vimos neste artigo como podemos manipular os dados de uma base de dados para outra de forma rápida utilizando a tecnologia DataSnap. Este exem-plo pode ser implementado e melhorado da forma que desejarem.

Espero que tenham gostado desta dica e até a próxima!

[email protected]

Jeferson Silva de LimaConsultor The Club.

Sobre o autor

Page 20: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201420

Listagem 1 – Exemplo de utilização da classe TOrdenaGrid

Olá pessoal, estamos trazendo mais uma vez uma dica para ajudar na visualização dos dados das aplicações feitas em Delphi. Sabemos o quanto uma ordenação bem aplicada facilita bastante na visualização e no entendimento das informações listadas. O que iremos propor aqui é que o

usuário possa utilizar mais de uma coluna para fazer a ordenação dos dados listados no DBGrid, e também terá a opção de ver os dados visualizados em ordem decrescente.

Como funcionará esta ordenação

Esta ordenação será feita através de duas propriedades do TClientDa-taSet, são elas: IndexFieldNames e IndexName. Na primeira propriedade, basta informarmos o campo pelo qual serão ordenados os dados, caso esta ordenação necessite ser aplicada em mais de um campo, os mesmos devem ser passados separados por “;” ponto e vírgula como por exemplo, “DATA; NOME”. A propriedade IndexFieldNames faz a ordenação apenas em ordem crescente. Para podermos fazer a ordenação de um campo em ordem decres-cente deveremos criar um índice para o campo do ClientDataSet. Este índice é do tipo TIndexDef , nele iremos indicar qual o campo será indexado e que será em ordem decrescente. Depois de criado o índice bastará indicarmos ele na propriedade IndexName do ClientDataSet.

Para sabermos em tempo de execução qual será a coluna a qual teremos que aplicar ordenação iremos utilizar o evento OnTitleClick do TDBGrid. Este evento nos informa qual a coluna fora clicada pelo usuário.

Nota: O ClientDataSet não precisa necessariamente estar vinculado a um banco de dados. Pode ser uma simples tabela temporária, ou o ClientDataSet pode estar acessando os dados de um arquivo XML, que a ordenação funcionará da mesma forma.

Encapsulando os métodos

Nesta dica iremos criar uma classe, TOrdenaGrid, para encapsular todos os métodos para a ordenação dos dados do ClientDataSet. Desta forma faci-litaremos a forma de utilizar este processo em mais de um formulário. Veja por exemplo na listagem 1 um como será feita a chamada desta classe para o controle da ordenação do DBGrid de um formulário qualquer.

var Form1: TForm1; objOrdenaGrid: TOrdenaGrid;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);beginobjOrdenaGrid := TOrdenaGrid.Create(DBGrid1, ClientDataSet1, Label_Ordenacao);end;

procedure TForm1.btnLimparOrdenacaoClick(Sender: TObject);beginif objOrdenaGrid <> nil then objOrdenaGrid.LimparOrdenacao;end;

Delphi - Criando uma classe para ordenação de DBGrids

Page 21: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 21

Listagem 3 – Estrutura da classe TOrdenaGrid

Listagem 4 – Codificação dos métodos públicos da classe TOrdenaGrid

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);beginif objOrdenaGrid <> nil then begin objOrdenaGrid.Free; objOrdenaGrid := nil; end;end;

Note que apenas criamos uma variável pública do tipo TOrdenaGrid e a instanciamos em memória informando os três parâmetros de entrada que são:

• DBGrid: Será quem receberá as ordenações• ClientDataSet: Deverá ser o ClientDataSet vinculado ao mesmo

DBGrid informado;• Label: Será o responsável por mostrar no formulário a ordenação

aplicada à grid.

Além disso no evento OnClick de um TButton chamamos o método Lim-parOrdenacao da classe. Ou seja, apenas com duas linhas em cada formulário será feita a ordenação dos DBGrids. O método Free é o destructor da classe, caso precise livrar o objeto da memória.

Criando a classe TOrdenaGrid

Abra uma nova Unit no Delphi e salve-a com o nome de unOrdenaGrid. Abaixo da palavra reservada “Interface” adicione as bibliotecas que iremos utilizar em nossa classe. Ver listagem 2.

uses SysUtils, Classes, StdCtrls, DBGrids, DBClient, DB;Listagem 2 – Bibliotecas utilizadas

Depois de adicionar as bibliotecas, iremos criar logo em seguida a decla-ração de nossa classe TOrdenaGrid. Transcreva logo abaixo das bibliotecas a codificação da listagem 3.

type TOrdenaGrid = class private { Atributos da classe TOrdenaGrid }

FcdsBase: TClientDataSet; FdbgDados: TDBGrid; FlbExibeOrdenacao: TLabel;FSufixoDec: String; { Métodos privados } function PreparaCamposOrdenados(Indices: String): String; procedure OrdenaGridTitleClick(Column: TColumn); procedure ExibeOrdenacao; public { Métodos públicos } constructor Create(DBG: TDBGrid; CDS: TClientDataSet; LBVisualizar: TLabel); destructor Free; procedure LimparOrdenacao; end;

Depois de transcrever a estrutura da classe clique com o direito do mou-se e acesse a opção de menu “Complete class at cursor” ou acesse o atalho de teclado (Ctrl + Shift + C) para gerar automaticamente as definições dos métodos da classe.

Agora iremos explicar cada método da classe para facilitar o entendimento da mesma.

Métodos Create, Free e LimparOrdenacao

Estes três métodos são os métodos públicos da classe.

O método Create é um construtor da classe. Ele é o responsável por instanciar a classe em memória. Nele temos três parâmetros, que são os componentes passados para os atributos da classe.

O método Free é o destructor da classe. Ele será utilizado para livrar da memória o objeto instanciado, e é através dele que iremos desvincular o mé-todo OrdenaGridTitleClick do evento OnTitleClick do DBGrid.

O método LimparOrdenacao remove os valores referentes a índices do ClientDataSet e exibe a ordenação.

Veja na listagem 4 a codificação destes métodos.

constructor TOrdenaGrid.Create(DBG: TDBGrid; CDS: TClientDataSet;

Page 22: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201422

Listagem 5 – Codificação do método OrdenaGridTitleClick LBVisualizar: TLabel);begin { Atribui aos atributos da classe os parâmetros passados. } FdbgDados := DBG; FcdsBase := CDS; FlbExibeOrdenacao := LBVisualizar; FdbgDados.OnTitleClick := OrdenaGridTitleClick; FSufixoDec := ‘_DECRESCENTE’; ExibeOrdenacao;end;

destructor TOrdenaGrid.Free;begin { Ao livrar o objeto da classe da memória, atribui nil ao evento OnTitleClick. } FdbgDados.OnTitleClick := nil;end;

procedure TOrdenaGrid.LimparOrdenacao;begin { Remove os valores dos indices do ClientDataSet e exibe a ordenação. } FcdsBase.IndexFieldNames := EmptyStr; FcdsBase.IndexName := EmptyStr; ExibeOrdenacao;end;

Note que além de atribuirmos os parâmetros aos atributos, também associamos ao evento OnTitleClick do atributo FdbgDados, o método Orde-naGridTitleClick. Desta forma poderemos saber qual coluna a ser ordenada. Logo em seguida definimos um valor para o atributo FSufixoDec, este valor será utilizado pelos métodos da classe na atribuição de indices. Depois chamamos o método ExibeOrdenacao para notificar através do atributo FlbExibeOrdenacao qual a ordenação atual do ClientDataSet.

Método OrdenaGridTitleClick

Este é um método privado e é dos principais métodosda classe,pois é ele quem irá verificar a coluna clicada e realizar todo o trabalho de aplicar a ordenação no ClientDataSet. Veja sua codificação na listagem 5.

procedure TOrdenaGrid.OrdenaGridTitleClick(Column: TColumn);var Indices: string;begin { Ativa os indices de acordo com as colunas clicadas }

Indices := FcdsBase.IndexFieldNames;

if (Pos(Column.FieldName, Indices) = 0) then begin { Se ainda não tiver a coluna no indice apenas adiciona }if Indices = EmptyStr then FcdsBase.IndexFieldNames := Column.FieldName else FcdsBase.IndexFieldNames := Format(‘%s; %s’, [Indices, Column.FieldName]); end else begin { Senão, cria o indice decrescente } Indices := AnsiUpperCase(Column.FieldName + FSufixoDec); FcdsBase.AddIndex(Indices, Column.FieldName, [ixDescending], ‘’, ‘’, 0); FcdsBase.IndexName := Indices; end;

FcdsBase.First; ExibeOrdenacao;end;

Neste método temos uma variável, Indices, que a princípio irá receber o valor da propriedade IndexFieldNames do ClientDataSet. Através desta vari-ável conseguimos verificar se a coluna que fora clicada pelo usuário já está adicionada ao indice ou não.

Caso ela ainda não tenha sido adicionada ao índice, verificamos se a vari-ável Indices está vazia, o que indica que ainda não há indices aplicados. Neste caso apenas adicionamos o nome do campo à propriedade IndexFieldNames. Entretanto, caso já tenha campos adicionados ao índice, temos que adicionar o próximo separando por “;” ponto e vírgula.

Page 23: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 23

Listagem 6 – Codificação dos métodos de exibição da ordenação do DBGrid

Caso a coluna clicada já tenha sido adicionada ao índice, a classe entenderá que esta coluna deverá ser ordenada em ordem decrescente, que é o que pode ser visto no bloco de código Else da verificação. Repare que a variável indices recebe o nome do campo concatenado com o atributo FSufixoDec. Depois criamos um índice com o nome indicado na variável Indices. Passando a opção ixDescending, indicamos que se trata de um indice ordenado em ordem decrescente. Depois disso, adicionamos o índice criado à propriedade IndexName do ClientDataSet.

Por fim, colocamos o ponteiro do ClientDataSet na primeira posição e chamamos o método ExibeOrdenacao para atualiza a visualização na Label.

Métodos ExibeOrdenacao e PreparaCamposOrdenados

Ambos os métodos são privados, ou seja, não podem ser acionados por outra classe que não a TOrdenaGrid.

O método PreparaCamposOrdenados é uma função que recebe uma string com os indices do ClientDataSet. Este método tem como função verificar quais são os campos indexados e assim retornar os valores da propriedade DisplayLabel dos respectivos campos numa String.

O método ExibeOrdenacao tem como função verificar qual a propriedade indexada no ClientDataSet, chamar o método PreparaCamposOrdenados para atribuir à Label de visualização a ordenação aplicada no DBGrid.

Veja na listagem 6 a codificação destes dois últimos métodos.

function TOrdenaGrid.PreparaCamposOrdenados(Indices: String): String;const Sep = ‘;’;var ST: TStringList; Campo: TField; I, Ate: Integer; S: String;begin { Retorna os filtros alterados para o DisplayLabel dos TFields }

Result := EmptyStr;if (Pos(Sep, Indices) = 0) and (Pos(FSufixoDec, Indices) = 0) then begin { Se não tiver nenhum separador e não for um indice decrescente... } Campo := FcdsBase.FindField(Indices); Result := Campo.

DisplayLabel; end elseif (Pos(FSufixoDec, Indices) > 0) then begin { senão, se for um indice decrescente... }Delete(Indices, Pos(FSufixoDec, Indices), Length(FSufixoDec)); Campo := FcdsBase.FindField(Indices); Result := Campo.DisplayLabel; end else begin { Senão, se for mais de um campo, teremos que dividi-lo... } ST := TStringList.Create; try ExtractStrings([‘;’], [‘ ‘], PAnsiChar(Indices), ST);

Ate := ST.Count - 1; for I := 0 to Ate do begin S := Trim(ST[I]); Campo := FcdsBase.FindField(S); Result := Result + Campo.DisplayLabel;

{ Enquanto não for a última passada do laço, adiciona “;”. }if I <> Ate then Result := Result + ‘, ‘; end; finally FreeAndNil(ST); end; end;end;

procedure TOrdenaGrid.ExibeOrdenacao;var Indices: String;begin { Exibe na Label FlbExibeOrdenacao a ordenação atual do FcdsBase }

if (FcdsBase.IndexFieldNames

Page 24: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201424

= EmptyStr) and (FcdsBase.IndexName = EmptyStr) then FlbExibeOrdenacao.Caption := ‘ Nenhuma ordenação ‘ elseif (FcdsBase.IndexFieldNames <> EmptyStr) then begin Indices := FcdsBase.IndexFieldNames; Indices := PreparaCamposOrdenados(Indices); FlbExibeOrdenacao.Caption := Format(‘ Ordenado por: [ %s ] ‘, [Indices]); end elseif (FcdsBase.IndexName <> EmptyStr) then begin Indices := FcdsBase.IndexName; Indices := PreparaCamposOrdenados(Indices); FlbExibeOrdenacao.Caption := Format(‘ Ordenação decrescente: [ %s ] ‘, [Indices]); end;end;

Nestes métodos temos mais linhas de código, mas é pelo fato de termos que fazer mais verificações. Notem que na função que prepara os campos indexados verificamos primeiramente o parâmetro passado refere-se a apenas um campo, para isso testamos a ausência do caracter “;” e a ausência do valor do atributo FSufixoDec. Na segunda verificação testamos se o indice é um indice decrescente. Por fim sabemos que se trata de um indice agrupado com mais de um campo. Neste caso quebramos a String e tratamos cada campo individualmente. O método ExibeOrdenacao verificará se o ClientDataSet se o ClientDataSet está com alguma ordenação e exibirá na propriedade Caption atributo FlbExibeOrdenacao a ordenação formatada pelo método Prepara-CamposOrdenados.

Testando a classe TOrdenaGrid

Bem, agora que acabamos de criar a nossa classe de ordenação de grids, vamos por ela em prática. Adicione em um formulário os seguintes compo-nentes: 1 ClientDataSet, 1 DBGrid, 1 TButton (name = btnLimparOrdenacao) e 1 Label (name = Label_Ordenacao).

Adicione alguns campos ao ClientDataSet, neste exemplo criamos três campos, são eles:

• ID: Tipo = Integer; DisplayLabel = “Id.”;

• NOME: Tipo = String(40); DisplayLabel = “Nome”;• DATA: Tipo = Date; DisplayLabel = “Data”.

Clique com o direito do mouse no ClientDataSet e acesse o item “Create DataSet” para trabalhar com o ClientDataSet apenas em memória.

Agora vamos as simples codificações. Adicione na biblioteca Uses a unit unOrdenaGrid. Feito isso agora é só transcrever as codificações da listagem 1 deste artigo. São apenas três chamadas. A primeira para instanciar o objeto em memória, a segunda para chamar o método LimparOrdenacao e a última para livrar da memória a instância do objeto.

Veja na figura 1 o formulário em execução sendo ordenado respectiva-mente pelos campos DATA e NOME em ordem crescente.

Figura 1 – DBGrid ordenado pelos campos DATA e NOME em ordem crescente

Conclusão

Neste artigo mostramos como criar uma classe para encapsular todos os métodos de ordenação de um DBGrid. Explicamos passo a passo a criação de cada método e qual sua respectiva função na classe. Mostramos também logo de início como é fácil a instanciação da classe em qualquer formulário.

Esperamos que este artigo tenha sido de alguma utilidade a você leitor. Um forte abraço e até a próxima.

[email protected]

Lucas Vieira de OliveiraConsultor Técnico The Club.

Sobre o autor

Page 25: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 25

Neste artigo irei abordar um tema muito usual em praticamente todos os sistemas que trabalhei até hoje, ensinarei de uma forma prática como devemos implementar o uso de Abas no sistema Android. Todo desenvolvedor já teve a necessidade de separar os dados por categorias em uma mesma tela, como por exemplo: Tipos de Pessoas: Jurídica e Física, em um cadastro de cliente, podemos também ter a necessidade de criar abas para separar dados cadas-trais e financeiros ou até mesmo em um pedido de venda, em se tratando de dispositivos móveis, temos que nos virar para encaixar diversas informações em uma única tela, nestes casos o uso de Abas se torna primordial e indis-pensável. Como de costume, antes de partir para a parte prática, irei discorrer sobre as classes e os principais métodos utilizados para o desenvolvimento do artigo. Para obtermos este efeito em nosso aplicativo, teremos como base as classes:”TabHost” e “TabSpec” e herdaremos nossa atividade da “TabActivity” e implementaremos os “OnTabChangeListener” e “TabContentFactory” para herdar múltiplos tipos de Interface. Aproveitaremos também este artigo para criar o layout proposto de uma forma dinâmica, veremos mais detalhes adiante.

Classe “TabHost”

Esta classe herda da “FrameLayout” e é denominada como um container para uma visão de janela com guias. Possui dois objetos principais, sendo: um conjunto de “Labels” para que o usuário possa clicar para selecionar uma guia específica e um Objeto FrameLayout que exibe o conteúdo da página. Os elementos individuais normalmente são controlados usando este objeto recipiente, em vez de definir os valores sobre os próprios elementos filho.

Métodos

1-) getTabHost(): Este método retorna o tabHost da atividade que está utilizando para armazenar as guias.

2-) setOnTabChangedListener(): Temos como parâmetro o contexto atual (this). Este método é disparado quando qualquer um dos itens da guia é selecionado ou alterado.

3-) addTab(): Serve para adicionar uma Guia. Possui como parâmetro o

Android - Criando Abas com TabHost e TabSpec

objeto da classe “TabSpec”, o qual especifica o conteúdo.4-) newtabSpec(): Método para definir propriedades para a guia. Possui

como retorno um objeto do tipo “TabSpec”. (Classe abordada no próximo tópico)

Exemplo:

TabSpec tabSpec1 = tabHost.newTabSpec(“Pessoa Fisica”);

Classe “TabSpec”

Responsável por possuir um indicador de guia, conteúdo e disponibiliza uma marca para usar e manter o controle do mesmo. Nesta classe temos algumas opções, como: Definir nomes, ícones, ID entre outros recursos. Ela possui como herança a classe do Tipo “Object”. Abaixo indicarei os métodos mais comuns.

Métodos

Ambos os métodos possuem 3 opções de escrita.

1-) setIndicator(): Tem como principal função especificar uma identificação para a aba.

Exemplo:

tabSpec1.setIndicator(“PessoaFisica”,getResources().getDrawable(R.drawable.fisica));

Page 26: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201426

No caso acima temos como primeiro parâmetro um Texto informativo e o segundo o ícone utilizado.

Outras implementações deste método:

public TabHost.TabSpec setIndicator (CharSequence label)

Utiliza como parâmetro apenas uma variável do tipo Texto.

public TabHost.TabSpec setIndicator (View view)

Neste caso apenas a View do contexto.

2-) setContent(): Em poucas palavras é através deste método que englo-bamos a classe da aba especificada. Passamos como parâmetro uma variável do tipo “Intent”.

Exemplo:

tabSpec1.setContent(new Intent(this,AbaPessoaFisica.class));

Outras implementações deste método:

public TabHost.TabSpec setContent (int viewId)

Passamos apenas o ID para obter o retorno.

public TabHost.TabSpec setContent (TabHost.TabContentFactory contentFactory)

Já neste método de escrita devemos enviar o objeto contendo todas as informações necessárias, do tipo “TabContentFactory”.

Criando o exemplo prático

O nosso exemplo envolverá 3 Atividades, sendo: a Aba Principal onde

conterá as Abas: Física e Jurídica. (“AbaPrincipal.java” , “AbaPessoaFisica.java” e “AbaPessoaJuridica.java”). Na aba invocaremos as classes acima abordadas. Montaremos no braço o layout utilizado com o auxílio da classe “LinearLayout” junto com componentes: “TextView”, “EditText” e “Button”. Para isto descre-verei todos os passos daqui pra frente. Inicie uma aplicação do Zero clicando em “File/New/Android Project...” Criando as três atividades descritas acima. Ver Imagem 01.

Figura 01: Classes.

Codificando o Exemplo

1-) Classe “AbaPessoaFisica.java”

Utilizaremos algumas bibliotecas adicionais para desenvolver este exem-plo, veja abaixo:

import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.view.Gravity;import android.view.ViewGroup.LayoutParams;import android.widget.Button;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.TextView;

É importante lembrar que ambas as abas (Pessoa Física e Pessoa Jurídica) irão herdar da classe “Activity”. Através do método “OnCreate” que iremos criar os objetos necessários para o layout. Confiram na codificação a seguir.

public class AbaPessoaFisica extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout linearLayout = new LinearLayout(this);

Page 27: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 27

linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); linearLayout.setBackgroundColor(Color.BLUE); linearLayout.setPadding(12, 12, 12, 12);

O primeiro passo seria instanciar um objeto do tipo “LinearLayout”, o qual armazenaremos todos os componentes que desejarmos. O método “se-tOrientation()” define o layout como Vertical, o “setlayoutParams()” alguns parâmetros de configuração e o “setBackgroundColor()” a cor de fundo. Já o método “setPadding()” as margens configuradas.

TextView tvNome = new TextView(this); tvNome.setText(“Nome”);tvNome.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); EditText etNome = new EditText(this); etNome.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); TextView tvCpf = new TextView(this); tvCpf.setText(“CPF”); tvCpf.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); EditText etCpf = new EditText(this); etCpf.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));

TextView tvRg = new TextView(this); tvRg.setText(“RG”); tvRg.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); EditText etRg = new EditText(this); etRg.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); Button btGravar = new Button(this); btGravar.setText(“Botão Pessoa Fisica”); btGravar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); btGravar.setGravity(Gravity.RIGHT);

Tanto para o TextView, EditText e Button seguimos o mesmo procedimento. Instanciamos o objeto e executamos alguns métodos referentes às configu-rações, como por exemplo “setText()” para adicionar rótulo no “TextView” e “Button” entre outras configurações básicas.

linearLayout.addView(tvNome); linearLayout.addView(etNome); linearLayout.addView(tvCpf); linearLayout.addView(etCpf); linearLayout.addView(tvRg); linearLayout.addView(etRg); linearLayout.addView(btGravar);

Adicionamos na tela estes componentes citados no momento em que invocamos o método “addView” do “LinearLayout”.

Page 28: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201428

Listagem 01: Aba Pessoa Física.

Listagem 02: Aba Pessoa Jurídica. setContentView(linearLayout);

Ao invés de chamarmos o arquivo de layout utilizando o “.xml”, podemos fazê-lo diretamente como foi realizado no código anterior, ou seja, teremos o objeto “linearLayout” como a View responsável pela Aba de Pessoa Física.

}}

Teremos o resultado na Imagem 02.

Figura 02: Aba Pessoa Física.

2-) Classe “AbaPessoaJuridica.java”

O código da classe “AbaPessoaJuridica.java” seguirá os mesmos passos descritos anteriormente. Teremos algumas diferenças de configurações de cor de Fundo e nome dos campos como por exemplo do “TextView” e do “Button”. Ver Listagem 02.

import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.view.Gravity;import android.view.ViewGroup.LayoutParams;import android.widget.Button;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.TextView;

public class AbaPessoaJuridica extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout linearLayout = new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); linearLayout.setBackgroundColor(Color.BLACK); linearLayout.setPadding(12, 12, 12, 12); TextView tvNome = new TextView(this); tvNome.setText(“Razão Social”); tvNome.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); EditText etNome = new EditText(this); etNome.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));

Page 29: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 29

TextView tvCpf = new TextView(this); tvCpf.setText(“CNPJ”); tvCpf.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); EditText etCpf = new EditText(this); etCpf.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); TextView tvIe = new TextView(this); tvIe.setText(“IE”); tvIe.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); EditText etIe = new EditText(this); etIe.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT)); Button btGravar = new Button(this); btGravar.setText(“Gravar Pessoa Juridica”); btGravar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)); btGravar.setGravity(Gravity.RIGHT); linearLayout.addView(tvNome); linearLayout.addView(etNome); linearLayout.addView(tvCpf); linearLayout.addView(etCpf); linearLayout.addView(tvIe); linearLayout.addView(etIe); linearLayout.

addView(btGravar); setContentView(linearLayout); }}

Teremos o resultado na Imagem 03.

Figura 03: Aba Pessoa Jurídica.

3-) Classe “AbaPrincipal.java”

Já nesta classe é onde utilizaremos as classes e métodos abordados no início do artigo. Englobaremos as classes “AbaPessoaFisica e AbaPessoaJuridica” implementadas anteriormente.

Importe os seguintes Namespaces.

import android.app.TabActivity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.TabHost;import android.widget.TabHost.OnTabChangeListener;import android.widget.TabHost.TabContentFactory;import android.widget.TabHost.TabSpec;import android.widget.TextView;

Page 30: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho201430

[email protected]

Thiago Cavalheiro Montebugnoliadora aprender novas tecnologias. Formado pela Faculdade de Tecnologia de Botucatu

– SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Atualmente trabalha no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

Sobre o autor

Esta classe irá herdar da TabActivity e implementar as múltiplas inter-faces “OnTabChangeListener e TabContentFactory”. É importante ressaltar que mesmo não utilizando os métodos “createTabContent(String tag)” e “onTabChanged(String tabId)” destas interfaces deveremos sobrescrevê-los com retornos nulos.

public class AbasPrincipal extends TabActivity implements OnTabChangeListener, TabContentFactory { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TabHost tabHost = getTabHost(); tabHost.setOnTabChangedListener(this); TabSpec tabSpec1 = tabHost.newTabSpec(“Pessoa Fisica”); tabSpec1.setIndicator(“Pessoa Fisica”,getResources().getDrawable(R.drawable.fisica)); tabSpec1.setContent(new Intent(this,AbaPessoaFisica.class)); TabSpec tabSpec2 = tabHost.newTabSpec(“Pessoa Juridica”); tabSpec2.setIndicator(“Pessoa Juridica”,getResources().getDrawable(R.drawable.juridica)); tabSpec2.setContent(new Intent(this,AbaPessoaJuridica.class)); tabHost.addTab(tabSpec1); tabHost.addTab(tabSpec2); } @Override

public View createTabContent(String tag) { return null; }

@Override public void onTabChanged(String tabId) { }}

No evento “Oncreate()” é onde estará concentrado a codificação neces-sária. Instanciaremos a classe “TabHost” para retornar o tabHost da atividade através do método “getTabHost()”. O método “setOnTabChangedListener()” será disparado quando qualquer um dos itens da guia é selecionado. Os dois métodos implementados na classe “Tabspec” são: o “setIndicator()” e o “setContent()” que respectivamente serve para especificar uma identificação para a aba e englobar e invocar a classe especificada. (Ambos explicados de-talhadamente no início do artigo). O último passo seria adicionar as guias no objeto “TabHost” através do método “addTab()”.

Conclusões

A minha intenção neste mês foi de aprofundar um pouco mais sobre um assunto de extrema importância no desenvolvimento de sistemas, o uso de Abas. Aproveitei também para os ensinar sobre criação dinâmica de “Layouts”, ou seja, tudo foi armazenado em uma classe “.java”, diferentemente dos outros artigos que tinham como base um arquivo “.xml”. Espero que com estas dicas os ajudem a desenvolver e implementar novas funcionalidades em seus sistemas.

Um abraço e até a próxima.

Referênciashttp://developer.android.com/reference/android/widget/TabHost.

TabSpec.html

Page 31: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014 05

Page 32: The Club - megazinetipos de linguagens e ferramentas de desenvolvimento. Nosso consultor técnico Lucas Vieira de Oliveira, trabalhando com Delphi, implementa uma classe específica

junho2014