O NeoMatrix Tech está de casa nova!

Você deverá ser redirecionado em 6 segundos. Se não, visite:
http://www.leonelfraga.com/neomatrixtech
e atualize seus favoritos.

Aviso IMPORTANTÍSSIMO!

Aviso aos navegantes:

O NeoMatrix Tech mudou de casa!!!

A partir de agora, acessem pelo novo endereço:

http://www.leonelfraga.com/neomatrixtech

Ué... mas é só o domínio mudou de lugar?

R: Na verdade, não é bem assim hehe. Este domínio que você acessa agora aponta para um blog hospedado no Blogger, enquanto no novo, aponta para um blog na plataforma Wordpress, hospedagem própria, muito mais rápida e com um layout mais agradável de ler ;)

Não vou fechar este domínio igual ao que eu fiz com o NM Light (que já está 100% na nova plataforma). Talvez beeeeeeem depois eu faça isso.

Todos os posts daqui se encontram lá, e novos posts serão colocados somente no novo endereço.
A única coisa que não consegui importar foram os comentários. Mas em breve vai ter um post contando sobre a epopéia que foi migrar o NeoMatrix Tech!

Somente vou fechar a área de comentários daqui. Caso queiram comentar, favor ver o post correspondente no "Novo NeoMatrix Tech" e comentem por lá. É bem melhor! (pena que os permalinks "amigáveis para SEO" não funcionam lá, dá erro 404 e não consigo fazer a configuração funcionar. E olha que eu já vi vários artigos falando desse assunto :( ).

Quem assina o feed, já está lendo o conteúdo do novo NeoMatrix Tech!

sábado, 7 de março de 2009

Simple PIM – Exemplo Nova Classe de Conexão – Parte 3: Web User Interface

Olá! E aí, após modelarmos o banco de dados, construir a biblioteca de classes e uma “quebra de gelo” com a Americanas anunciando GeForce 2 à 1500 Reais em pleno 2009 (Nem Radeon HD 4870 custa isso!), vamos à penúltima parte (na verdade, a última no que se refere a códigos hehe) da construção do nosso Simple PIM (Personal Information Manager), onde iremos construir sua interface web.

A Interface Web será construída em apenas uma página (Single Page Application), sendo TODOS os cadastros implementados através de janelas modais, utilizando mais uma vez a ótima biblioteca jQuery e seu plugin jqModal.

Vamos ver com mais carinho aquele screenshot da solution da segunda parte agora? (após o break ;-) )

Separamos, em diretórios, os arquivos conforme o seu tipo:

Bin: Arquivos compilados, bibliotecas de classe.

css: Folhas de estilo, para a formatação dos elementos da UI.

javascript: Arquivos de script em JavaScript.

imagens: Imagens que farão parte do sistema (neste, particularmente, não coloquei imagens).

Na raíz, encontram-se o web.config, a master page (sim, embora tenha apenas uma página, preferi utilizar master pages neste projeto) e o index.aspx, que é onde tudo acontece.

Vamos primeiro olhar a parte de design:

   1: <%@ Page Language="C#" MasterPageFile="~/principal.master" AutoEventWireup="true"
   2:     CodeFile="index.aspx.cs" Inherits="index" Title="Simple PIM by NeoMatrix Tech" %>
   3:  
   4: <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
   5:     <div>
   6:         <asp:UpdatePanel runat="server" ID="updGeral">
   7:             <ContentTemplate>
   8:                 <div style="width:100%;text-align:center">
   9:                     <span class="fonte-peq">Escolha o módulo desejado:</span>
  10:                     <asp:DropDownList runat="server" ID="ddlEscolheMod" CssClass="tbx-normal" AutoPostBack="true"
  11:                         OnSelectedIndexChanged="ddlEscolheMod_SelectedIndexChange">
  12:                         <asp:ListItem Value="1" Text="Cadastro de Contatos"></asp:ListItem>
  13:                         <asp:ListItem Value="2" Text="Cadastro de Formas de Contato"></asp:ListItem>
  14:                     </asp:DropDownList>
  15:                 </div>
  16:                 <hr />
  17:                 <asp:Panel runat="server" ID="pnlCadContato">
  18:                     <div style="text-align:center;width:100%;">
  19:                         <asp:Button runat="server" ID="btnFiltrarContato" Text="Filtrar" OnClick="btnFiltrarContato_Click" CssClass="botoes" />
  20:                         <asp:Button runat="server" ID="btnNovoContato" Text="Novo Contato" OnClick="btnNovo_Click" CssClass="botoes" CommandArgument="TContato,0,dvDetContato" /><br />
  21:                     </div>
  22:                     <br />
  23:                     <asp:GridView runat="server" ID="grdContatos" AutoGenerateColumns="false" DataKeyNames="Id" Width="100%">
  24:                     <RowStyle CssClass="grid-normalitem" />
  25:                     <HeaderStyle CssClass="grid-header" />
  26:                         <Columns>
  27:                             <asp:BoundField HeaderText="Nome" DataField="Nome" />
  28:                             <asp:BoundField HeaderText="Sobrenome" DataField="Sobrenome" />
  29:                             <asp:BoundField HeaderText="Dt. Nascimento" DataField="DtNascimento" DataFormatString="{0:dd/MM/yyyy}" />
  30:                             <asp:BoundField HeaderText="Sexo" DataField="Sexo" />
  31:                             <asp:BoundField HeaderText="Profissão" DataField="Profissao" />
  32:                             <asp:TemplateField>
  33:                                 <ItemTemplate>
  34:                                     <asp:Button runat="server" ID="btnEditarContato" Text="Editar" CommandArgument='<%#Bind("Id","TContato,{0},dvDetContato")%>'
  35:                                         OnClick="btnEditar_Click" CssClass="botoes-grid" />
  36:                                     <asp:Button runat="server" ID="btnExcluirContato" Text="Excluir" CommandArgument='<%#Bind("Id","TContato,{0},dvDetContato")%>' CssClass="botoes-grid" OnClick="btnExcluir_Click" />
  37:                                 </ItemTemplate>
  38:                             </asp:TemplateField>
  39:                         </Columns>
  40:                     </asp:GridView>
  41:                 </asp:Panel>
  42:                 <asp:Panel runat="server" ID="pnlCadFC" Visible="false">
  43:                     <div style="text-align:center;width:100%;">
  44:                         <asp:Button runat="server" ID="btnFiltrarTFC" Text="Filtrar" OnClick="btnFiltrarTFC_Click" CssClass="botoes" />
  45:                         <asp:Button runat="server" ID="btnNovoTFC" Text="Novo Tipo de Forma de Contato" OnClick="btnNovo_Click" CssClass="botoes" CommandArgument="TTpFormaContato,0,dvDetTpFormaContato" /><br />
  46:                     </div>
  47:                     <br />
  48:                     <asp:GridView runat="server" ID="grdTipoFC" AutoGenerateColumns="false" DataKeyNames="Id" Width="100%">
  49:                     <RowStyle CssClass="grid-normalitem" />
  50:                     <HeaderStyle CssClass="grid-header" />
  51:                         <Columns>
  52:                             <asp:BoundField HeaderText="Descrição" DataField="Descricao" />
  53:                             <asp:TemplateField>
  54:                                 <ItemTemplate>
  55:                                     <asp:Button runat="server" ID="btnEditarTFC" Text="Editar" CommandArgument='<%#Bind("Id","TTpFormaContato,{0},dvDetTpFormaContato")%>'
  56:                                         OnClick="btnEditar_Click" CssClass="botoes-grid" />
  57:                                     <asp:Button runat="server" ID="btnExcluirTFC" Text="Excluir" CommandArgument='<%#Bind("Id","TTpFormaContato,{0},dvDetTpFormaContato")%>' CssClass="botoes-grid" OnClick="btnExcluir_Click" />
  58:                                 </ItemTemplate>
  59:                             </asp:TemplateField>
  60:                         </Columns>
  61:                     </asp:GridView>
  62:                 </asp:Panel>
  63:             </ContentTemplate>
  64:         </asp:UpdatePanel>
  65:     </div>
  66:     <div id="dvDetContato" class="jqmWindow" style="overflow: auto; width: 700px; height: 500px;">
  67:         <asp:UpdatePanel runat="server" ID="updContatos">
  68:             <ContentTemplate>
  69:                 <div class="titulos-secao">
  70:                     <span>Detalhes do Contato</span>
  71:                 </div>
  72:                 <div style="width: 80px; float: left">
  73:                     <span class="fonte-peq">Código</span><br />
  74:                     <asp:TextBox ID="tbxTContatoId" runat="server" CssClass="tbx-ro" Width="70px" ReadOnly="true"></asp:TextBox>
  75:                 </div>
  76:                 <div style="width: 250px; float: left">
  77:                     <span class="fonte-peq">Nome</span><br />
  78:                     <asp:TextBox ID="tbxTContatoNome" runat="server" CssClass="tbx-normal" Width="240px"></asp:TextBox>
  79:                 </div>
  80:                 <div style="width: 250px; float: none;">
  81:                     <span class="fonte-peq">Sobrenome</span><br />
  82:                     <asp:TextBox ID="tbxTContatoSobrenome" runat="server" CssClass="tbx-normal" Width="240px"></asp:TextBox>
  83:                 </div>
  84:                 <div style="width: 150px; float: left;">
  85:                     <span class="fonte-peq">Data de Nascimento</span><br />
  86:                     <asp:TextBox ID="tbxTContatoDtNascimento" runat="server" CssClass="tbx-normal" Width="90px"></asp:TextBox>
  87:                 </div>
  88:                 <div style="width: 160px; float: left;">
  89:                     <span class="fonte-peq">SEXO</span><br />
  90:                     <asp:DropDownList ID="ddlTContatoSexo" runat="server" CssClass="tbx-normal" Width="150px">
  91:                         <asp:ListItem Value="M" Text="MASC."></asp:ListItem>
  92:                         <asp:ListItem Value="F" Text="FEM."></asp:ListItem>
  93:                         <asp:ListItem Value="G" Text="GAY"></asp:ListItem>
  94:                         <asp:ListItem Value="L" Text="LÉSBICA"></asp:ListItem>
  95:                         <asp:ListItem Value="B" Text="BISSEXUAL"></asp:ListItem>
  96:                         <asp:ListItem Value="T" Text="TRANSSEXUAL"></asp:ListItem>
  97:                         <asp:ListItem Value="E" Text="METROSSEXUAL"></asp:ListItem>
  98:                     </asp:DropDownList>
  99:                 </div>
 100:                 <div style="width: 160px; float: left;">
 101:                     <span class="fonte-peq">RG</span><br />
 102:                     <asp:TextBox ID="tbxTContatoRg" runat="server" CssClass="tbx-normal" Width="150px"></asp:TextBox>
 103:                 </div>
 104:                 <div style="width: 160px; float: none">
 105:                     <span class="fonte-peq">CPF</span><br />
 106:                     <asp:TextBox ID="tbxTContatoCpf" runat="server" CssClass="tbx-normal" Width="150px"></asp:TextBox>
 107:                 </div>
 108:                 <div style="width: 160px; float: left;">
 109:                     <span class="fonte-peq">CNH</span><br />
 110:                     <asp:TextBox ID="tbxTContatoCnh" runat="server" CssClass="tbx-normal" Width="150px"></asp:TextBox>
 111:                 </div>
 112:                 <div style="width: 250px; float: none">
 113:                     <span class="fonte-peq">PROFISSAO</span><br />
 114:                     <asp:TextBox ID="tbxTContatoProfissao" runat="server" CssClass="tbx-normal" Width="240px"></asp:TextBox>
 115:                 </div>
 116:                 <br />
 117:                 <div style="text-align:center;background-color:Black;width:100%;">
 118:                     <asp:Button runat="server" ID="btnSalvarDetContato" Text="Salvar Contato" OnClick="btnSalvarDetContato_Click" CssClass="botoes" />
 119:                     <asp:Button runat="server" ID="btnFecharDetContato" Text="Fechar" OnClientClick="$dvDetContato.jqmHide(); return false;" CssClass="botoes" />
 120:                 </div>
 121:                 <br />
 122:                 <div style="border: solid 1px black; height: 200px; width: 100%; overflow: auto;">
 123:                     <div class="titulos-secao">
 124:                         <span>Endereços</span>
 125:                     </div>
 126:                     <div style="width:100%;text-align:center;">
 127:                         <asp:Button runat="server" ID="btnNovoEndereco" Text="Novo Endereço" OnClick="btnNovo_Click" CssClass="botoes" CommandArgument="TEndereco,0,dvDetEndereco" />
 128:                     </div>
 129:                     <br />
 130:                     <asp:GridView runat="server" ID="grdTContatoListaEnderecos" AutoGenerateColumns="false"
 131:                         DataKeyNames="Id" Width="100%">
 132:                     <RowStyle CssClass="grid-normalitem" />
 133:                     <HeaderStyle CssClass="grid-header" />
 134:                         <Columns>
 135:                             <asp:BoundField HeaderText="Logradouro" DataField="Logradouro" />
 136:                             <asp:BoundField HeaderText="Numero" DataField="Numero" />
 137:                             <asp:BoundField HeaderText="Cidade" DataField="Cidade" />
 138:                             <asp:BoundField HeaderText="Estado" DataField="Estado" />
 139:                             <asp:TemplateField>
 140:                                 <ItemTemplate>
 141:                                     <asp:Button runat="server" ID="btnEditarEndereco" Text="Editar" CommandArgument='<%#Bind("Id","TEndereco,{0},dvDetEndereco")%>'
 142:                                         OnClick="btnEditar_Click" CssClass="botoes-grid" />
 143:                                     <asp:Button runat="server" ID="btnExcluirEndereco" Text="Excluir" CommandArgument='<%#Bind("Id","TEndereco,{0},dvDetEndereco")%>' CssClass="botoes-grid"  OnClick="btnExcluir_Click"/>
 144:                                 </ItemTemplate>
 145:                             </asp:TemplateField>
 146:                         </Columns>
 147:                     </asp:GridView>
 148:                 </div>
 149:                 <br />
 150:                 <div style="border: solid 1px black; height: 200px; width: 100%; overflow: auto;">
 151:                     <div class="titulos-secao">
 152:                         <span>Formas de Contato</span>
 153:                     </div>
 154:                     <div style="text-align:center;width:100%;">
 155:                     <asp:Button runat="server" ID="btnNovoFormaContato" Text="Nova Forma de Contato"
 156:                         OnClick="btnNovo_Click" CssClass="botoes" CommandArgument="TFormaContato,0,dvDetFormaContato" />
 157:                     </div>    
 158:                     <asp:GridView runat="server" ID="grdTContatoListaFormaContato" AutoGenerateColumns="false"
 159:                         DataKeyNames="Id" Width="100%">
 160:                     <RowStyle CssClass="grid-normalitem" />
 161:                     <HeaderStyle CssClass="grid-header" />
 162:                         <Columns>
 163:                             <asp:BoundField HeaderText="Forma de Contato" DataField="DescricaoFormaContato" />
 164:                             <asp:BoundField HeaderText="Valor" DataField="Valor" />
 165:                             <asp:TemplateField>
 166:                                 <ItemTemplate>
 167:                                     <asp:Button runat="server" ID="btnEditarFC" Text="Editar" CommandArgument='<%#Bind("Id","TFormaContato,{0},dvDetFormaContato")%>'
 168:                                         OnClick="btnEditar_Click" CssClass="botoes-grid" />
 169:                                     <asp:Button runat="server" ID="btnExcluirFC" Text="Excluir" CommandArgument='<%#Bind("Id","TFormaContato,{0},dvFormaDetContato")%>' CssClass="botoes-grid"  OnClick="btnExcluir_Click"/>
 170:                                 </ItemTemplate>
 171:                             </asp:TemplateField>
 172:                         </Columns>
 173:                     </asp:GridView>
 174:                 </div>
 175:             </ContentTemplate>
 176:         </asp:UpdatePanel>
 177:     </div>
 178:     <div id="dvDetEndereco" class="jqmWindow" style="z-index: 3001;">
 179:         <asp:UpdatePanel runat="server" ID="updDetEndereco">
 180:             <ContentTemplate>
 181:                 <div class="titulos-secao">
 182:                     <span>Detalhes do Endereço</span>
 183:                 </div>
 184:                 <!-- A classe TContato é a que irá setar este campo, a PK da tabela de Endereços aponta para ele -->
 185:                 <input type="hidden" id="hdfTContatoId" runat="server" />
 186:                 <div style="width: 160px;">
 187:                     <span class="fonte-peq">ID</span><br />
 188:                     <asp:TextBox ID="tbxTEnderecoId" runat="server" CssClass="tbx-ro" Width="150px" ReadOnly="true"></asp:TextBox>
 189:                 </div>
 190:                 <div style="width: 160px;">
 191:                     <span class="fonte-peq">Tipo de Logradouro</span><br />
 192:                     <asp:DropDownList ID="ddlTEnderecoTipoLogradouro" runat="server" CssClass="tbx-normal"
 193:                         Width="150px">
 194:                         <asp:ListItem Text="Rua" Value="R"></asp:ListItem>
 195:                         <asp:ListItem Text="Avenida" Value="AV"></asp:ListItem>
 196:                         <asp:ListItem Text="Alameda" Value="AL"></asp:ListItem>
 197:                         <asp:ListItem Text="Travessa" Value="TV"></asp:ListItem>
 198:                         <asp:ListItem Text="Beco" Value="B"></asp:ListItem>
 199:                         <asp:ListItem Text="Praça" Value="PC"></asp:ListItem>
 200:                         <asp:ListItem Text="Rodovia" Value="ROD"></asp:ListItem>
 201:                     </asp:DropDownList>
 202:                 </div>
 203:                 <div style="width: 210px; float: left;">
 204:                     <span class="fonte-peq">Logradouro</span><br />
 205:                     <asp:TextBox ID="tbxTEnderecoLogradouro" runat="server" CssClass="tbx-normal" Width="200px"></asp:TextBox>
 206:                 </div>
 207:                 <div style="width: 160px; float: left;">
 208:                     <span class="fonte-peq">Número</span><br />
 209:                     <asp:TextBox ID="tbxTEnderecoNumero" runat="server" CssClass="tbx-normal" Width="150px"></asp:TextBox>
 210:                 </div>
 211:                 <div style="width: 160px; float: none;">
 212:                     <span class="fonte-peq">Complemento</span><br />
 213:                     <asp:TextBox ID="tbxTEnderecoComplemento" runat="server" CssClass="tbx-normal" Width="150px"></asp:TextBox>
 214:                 </div>
 215:                 <div style="width: 160px; float: left;">
 216:                     <span class="fonte-peq">Cep</span><br />
 217:                     <asp:TextBox ID="tbxTEnderecoCep" runat="server" CssClass="tbx-normal" Width="150px"></asp:TextBox>
 218:                 </div>
 219:                 <div style="width: 300px; float: none;">
 220:                     <span class="fonte-peq">Bairro</span><br />
 221:                     <asp:TextBox ID="tbxTEnderecoBairro" runat="server" CssClass="tbx-normal" Width="290px"></asp:TextBox>
 222:                 </div>
 223:                 <div style="width: 260px; float: left;">
 224:                     <span class="fonte-peq">Cidade</span><br />
 225:                     <asp:TextBox ID="tbxTEnderecoCidade" runat="server" CssClass="tbx-normal" Width="250px"></asp:TextBox>
 226:                 </div>
 227:                 <div style="width: 40px; float: none;">
 228:                     <span class="fonte-peq">UF</span><br />
 229:                     <asp:TextBox ID="tbxTEnderecoEstado" runat="server" CssClass="tbx-normal" Width="30px"
 230:                         MaxLength="2"></asp:TextBox>
 231:                 </div>
 232:                 <div style="text-align:center;width:100%;">
 233:                     <asp:Button runat="server" ID="btnSalvaEndereco" Text="Salvar" OnClick="btnSalvaEndereco_Click" CssClass="botoes" />
 234:                     <asp:Button runat="server" ID="btnFecharEndereco" Text="Fechar" OnClientClick="$dvDetEndereco.jqmHide();return false;" CssClass="botoes" />
 235:                 </div>
 236:             </ContentTemplate>
 237:         </asp:UpdatePanel>
 238:     </div>
 239:     <div id="dvDetFormaContato" class="jqmWindow" style="z-index: 3001;">
 240:         <asp:UpdatePanel runat="server" ID="updDetFC">
 241:             <ContentTemplate>
 242:                 <div class="titulos-secao">
 243:                     <span>Detalhes da Forma de Contato</span>
 244:                 </div>
 245:                 <input type="hidden" id="hdfTFormaContatoContatoId" runat="server" />
 246:                 <div style="width: 80px; float: left;">
 247:                     <span class="fonte-peq">ID</span><br />
 248:                     <asp:TextBox ID="tbxTFormaContatoId" runat="server" CssClass="tbx-normal" Width="70px"></asp:TextBox>
 249:                 </div>
 250:                 <div style="width: 210px; float: none;">
 251:                     <span class="fonte-peq">Forma de Contato:</span><br />
 252:                     <asp:DropDownList ID="ddlTFormaContatoTpFormaContatoId" runat="server" CssClass="tbx-normal"
 253:                         Width="200px" DataTextField="Descricao" DataValueField="Id">
 254:                     </asp:DropDownList>
 255:                 </div>
 256:                 <div style="width: 250px;">
 257:                     <span class="fonte-peq">Valor:</span><br />
 258:                     <asp:TextBox ID="tbxTFormaContatoValor" runat="server" CssClass="tbx-normal" Width="240px"></asp:TextBox>
 259:                 </div>
 260:                 <div style="width:100%;text-align:center;">
 261:                     <asp:Button runat="server" ID="btnSalvaFC" Text="Salvar" OnClick="btnSalvaFC_Click" CssClass="botoes" />
 262:                     <asp:Button runat="server" ID="btnFechaFC" Text="Fechar" OnClientClick="$dvDetFormaContato.jqmHide(); return false;" CssClass="botoes" />
 263:                 </div>
 264:             </ContentTemplate>
 265:         </asp:UpdatePanel>
 266:     </div>
 267:     <div id="dvDetTpFormaContato" class="jqmWindow">
 268:         <asp:UpdatePanel runat="server" ID="updDetTpFC">
 269:             <ContentTemplate>
 270:                 <div class="titulos-secao">
 271:                     <span>Detalhes do Tipo de Forma de Contato</span>
 272:                 </div>
 273:                 <div style="width: 90px; float: left;">
 274:                     <span class="fonte-peq">Cód.</span><br />
 275:                     <asp:TextBox ID="tbxTTpFormaContatoId" runat="server" CssClass="tbx-normal" Width="80px"
 276:                         ReadOnly="true"></asp:TextBox>
 277:                 </div>
 278:                 <div style="width: 210px; float: none;">
 279:                     <span class="fonte-peq">Descrição</span><br />
 280:                     <asp:TextBox ID="tbxTTpFormaContatoDescricao" runat="server" CssClass="tbx-normal"
 281:                         Width="200px"></asp:TextBox>
 282:                 </div>
 283:                 <div style="text-align:center;width:100%;">
 284:                     <asp:Button runat="server" ID="btnSalvaTFC" Text="Salvar"
 285:                         OnClick="btnSalvaTFC_Click" CssClass="botoes" />
 286:                     <asp:Button runat="server" ID="Button1" Text="Fechar" OnClientClick="$dvDetTpFormaContato.jqmHide(); return false;" CssClass="botoes" />
 287:                 </div>
 288:             </ContentTemplate>
 289:         </asp:UpdatePanel>
 290:     </div>
 291:  
 292:     <script type="text/javascript">
   1:  
   2:             //Inicializa os Modais
   3:            var $dvDetContato = $('#dvDetContato').jqm({modal:true,toTop:true,trigger:false});
   4:            var $dvDetEndereco = $('#dvDetEndereco').jqm({modal:true,toTop:true,trigger:false});
   5:            var $dvDetFormaContato = $('#dvDetFormaContato').jqm({modal:true,toTop:true,trigger:false});
   6:            var $dvDetTpFormaContato = $('#dvDetTpFormaContato').jqm({modal:true,toTop:true,trigger:false});
   7:     
</script>
 293:  
 294: </asp:Content>

Ele pode assustar por ser gigante, mas lembre-se: a aplicação toda está contida apenas nesta página.

Temos no final um bloco de JavaScript que faz a inicialização das janelas modais do nosso sistema, usando o jQuery.

A página é composta de cinco (5) div’s principais, que representam o cadastro. O primeiro, sem um ID, é o div que corresponde à grade de pesquisa e é a primeira coisa que é mostrada para o usuário quando o site é acessado.

Nesta página, fizemos o mesmo esquema que foi feito no Cadastro de Usuários em ASP.NET (lembra?), ou seja, a página principal corresponde a 2 cadastros: Cadastro de Contatos e Tipos de Forma de Contato, sendo alternados via combo-box.

As telas de visualização, inserção e alteração de dados são janelas modais, sendo o Cadastro de Contatos e o de Tipo de Forma de Contato pertencentes à página principal: são superpostas diretamente a esta.

Já o Cadastro de Endereços e Formas de Contato, pertencem ao Cadastro de Contatos, ou seja, cada endereço e forma de contato pertencem a um contato. Portanto, estas janelas são superpostas ao Cadastro de Contato.

Por causa disto, temos a maior particularidade do design desta página em relação ao Controle de Usuários: janela modal sobre outra janela modal.

Note que nos div’s dvDetEndereco e dvDetFormaContato temos explicitamente declarado o atributo z-index com o valor 3001.

Os div’s contendo o valor jqmWindow no atributo class são janelas modais. Esta classe CSS é utilizada pelo jqModal exatamente para isso: definir os atributos das janelas modais.

O jqmWindow é definido dentro do arquivo jqModal.css, e nele, o atributo z-index padrão de cada modal é 3000.

Para obtermos a superposição de janelas modais, devemos declarar esta janela com um z-index MAIOR do que a modal que estará atrás dela. Como não dá para criar uma classe CSS para cada nível de modal, devemos sobreescrever o atributo z-index colocando-o diretamente na declaração do div a ser colocado em uma camada acima de outra.

Fazendo isso, o jqModal irá atribuir o z-index que declaramos explicitamente ao invés do z-index configurado na classe jqmWindow.

Hum… notaram mais alguma coisa de diferente aí? “O que é que você está passando no CommandArgument de cada botão Novo e nos Editar e Excluir dos grids? Antes você só passava a chave do registro…”.

Vamos ver isso analisando o code-behind:

   1: using System;
   2: using System.Data;
   3: using System.Configuration;
   4: using System.Collections;
   5: using System.Web;
   6: using System.Web.Security;
   7: using System.Web.UI;
   8: using System.Web.UI.WebControls;
   9: using System.Web.UI.WebControls.WebParts;
  10: using System.Web.UI.HtmlControls;
  11: using System.Runtime.Remoting;
  12: using System.Reflection;
  13: using SPIMCore;
  14:  
  15: public partial class index : System.Web.UI.Page
  16: {
  17:     protected void Page_Load(object sender, EventArgs e)
  18:     {
  19:         if (!IsPostBack)
  20:         {
  21:             ddlTFormaContatoTpFormaContatoId.DataSource = TTpFormaContato.ListarTodos();
  22:             ddlTFormaContatoTpFormaContatoId.DataBind();
  23:         }
  24:     }
  25:  
  26:     protected void ddlEscolheMod_SelectedIndexChange(object sender, EventArgs e)
  27:     {
  28:         pnlCadContato.Visible = (sender as DropDownList).SelectedValue.Equals("1");
  29:         pnlCadFC.Visible = (sender as DropDownList).SelectedValue.Equals("2");
  30:     }
  31:  
  32:     protected void RefreshGrids()
  33:     {
  34:         grdContatos.DataSource = TContato.ListarTodos();
  35:         grdContatos.DataBind();
  36:  
  37:         if (!tbxTContatoId.Text.Equals(""))
  38:         {
  39:             grdTContatoListaEnderecos.DataSource = TEndereco.ListarPorContato(Int32.Parse(tbxTContatoId.Text));
  40:             grdTContatoListaEnderecos.DataBind();
  41:  
  42:             grdTContatoListaFormaContato.DataSource = TFormaContato.ListarPorContato(Int32.Parse(tbxTContatoId.Text));
  43:             grdTContatoListaFormaContato.DataBind();
  44:         }
  45:  
  46:         grdTipoFC.DataSource = TTpFormaContato.ListarTodos();
  47:         grdTipoFC.DataBind();
  48:     }
  49:  
  50:     #region Rotnias Comuns a todos os botões dos Modais
  51:     /// <summary>
  52:     /// Botão Editar dos gridviews
  53:     /// </summary>
  54:     /// <param name="sender"></param>
  55:     /// <param name="e"></param>
  56:     protected void btnEditar_Click(object sender, EventArgs e)
  57:     {
  58:         string[] args = (sender as Button).CommandArgument.Split(new char[1] { ',' });
  59:         ObjectHandle clsCad = Activator.CreateInstance("SPIMCore", String.Format("SPIMCore.{0}", args[0]));
  60:         Type t = clsCad.Unwrap().GetType();
  61:         t.InvokeMember("SetByID", BindingFlags.InvokeMethod, null, clsCad.Unwrap(), new object[] { new object[1] { Int32.Parse(args[1]) } });
  62:         t.InvokeMember("BindToUI", BindingFlags.InvokeMethod, null, clsCad.Unwrap(), new object[] { this, this.GetType(), new ArrayList() });
  63:         string script = String.Format("${0}.jqmShow();", args[2]);
  64:         ScriptManager.RegisterStartupScript(this, this.GetType(), "abremodal", script, true);
  65:     }
  66:  
  67:     /// <summary>
  68:     /// Botão Novo
  69:     /// </summary>
  70:     /// <param name="sender"></param>
  71:     /// <param name="e"></param>
  72:     protected void btnNovo_Click(object sender, EventArgs e)
  73:     {
  74:         //Não permite o Bind de combo-boxes (PK's)
  75:         ArrayList notbind = new ArrayList();
  76:         notbind.Add("ddlTFormaContatoTpFormaContatoId");
  77:         
  78:         
  79:         string[] args = (sender as Button).CommandArgument.Split(new char[1] { ',' });
  80:         ObjectHandle clsCad = Activator.CreateInstance("SPIMCore", String.Format("SPIMCore.{0}", args[0]));
  81:         Type t = clsCad.Unwrap().GetType();
  82:         t.InvokeMember("BindToUI", BindingFlags.InvokeMethod, null, clsCad.Unwrap(), new object[] { this, this.GetType(), notbind });
  83:         string script = String.Format("${0}.jqmShow();", args[2]);
  84:         ScriptManager.RegisterStartupScript(this, this.GetType(), "abremodal", script, true);    
  85:     }
  86:  
  87:     /// <summary>
  88:     /// Botão de Exclusão dos gridviews
  89:     /// </summary>
  90:     /// <param name="sender"></param>
  91:     /// <param name="e"></param>
  92:     protected void btnExcluir_Click(object sender, EventArgs e)
  93:     {
  94:         string[] args = (sender as Button).CommandArgument.Split(new char[1] { ',' });
  95:         ObjectHandle clsCad = Activator.CreateInstance("SPIMCore", String.Format("SPIMCore.{0}", args[0]));
  96:         Type t = clsCad.Unwrap().GetType();
  97:         t.InvokeMember("SetByID", BindingFlags.InvokeMethod, null, clsCad.Unwrap(), new object[] { new object[1] { Int32.Parse(args[1]) } });
  98:         t.InvokeMember("Delete", BindingFlags.InvokeMethod, null, clsCad.Unwrap(), null);
  99:  
 100:         PropertyInfo pi = t.GetProperty("MsgInfo");
 101:  
 102:         string script = Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(pi.GetValue(clsCad.Unwrap(), null).ToString()), false);
 103:         ScriptManager.RegisterStartupScript(this, this.GetType(), "abremodal", script, true);
 104:  
 105:         RefreshGrids();
 106:     }
 107:  
 108:     #endregion
 109:  
 110:     #region Detalhes do Contato
 111:     protected void btnSalvarDetContato_Click(object sender, EventArgs e)
 112:     {
 113:         TContato contato = new TContato();
 114:         string script = "";
 115:         
 116:         contato.BindFromUI(this, this.GetType(), new ArrayList());
 117:         bool ok = (tbxTContatoId.Text.Equals("") || tbxTContatoId.Text.Equals("0")) ? contato.Insert() : contato.Update();
 118:         
 119:         script += Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(contato.MsgInfo), false);
 120:         script += ok ? "$dvDetContato.jqmHide();" : "";
 121:         if (ok)
 122:         {
 123:             grdContatos.DataSource = TContato.ListarTodos();
 124:             grdContatos.DataBind();
 125:         }
 126:         
 127:         ScriptManager.RegisterStartupScript(this, this.GetType(), "salvacontato", script, true);
 128:     }
 129:  
 130:     protected void btnFiltrarContato_Click(object sender, EventArgs e)
 131:     {
 132:         grdContatos.DataSource = TContato.ListarTodos();
 133:         grdContatos.DataBind();
 134:     }    
 135:     #endregion
 136:  
 137:     #region Modal de Endereços
 138:     protected void btnSalvaEndereco_Click(object sender, EventArgs e)
 139:     {
 140:         TEndereco endereco = new TEndereco();
 141:         string script = "";
 142:  
 143:         endereco.BindFromUI(this, this.GetType(), new ArrayList());
 144:         endereco.ContatoId = Int32.Parse(hdfTContatoId.Value); //o único que deve ser setado manualmente
 145:         bool ok = (tbxTEnderecoId.Text.Equals("") || tbxTEnderecoId.Text.Equals("0")) ? endereco.Insert() : endereco.Update();
 146:  
 147:         script += Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(endereco.MsgInfo), false);
 148:         script += ok ? "$dvDetEndereco.jqmHide();" : "";
 149:         if (ok)
 150:         {
 151:             grdTContatoListaEnderecos.DataSource = TEndereco.ListarPorContato(Int32.Parse(tbxTContatoId.Text));
 152:             grdTContatoListaEnderecos.DataBind();
 153:         }
 154:  
 155:         ScriptManager.RegisterStartupScript(this, this.GetType(), "salvacontato", script, true);
 156:     }
 157:     #endregion
 158:  
 159:     #region Modal de Formas de Contato
 160:  
 161:     protected void btnSalvaFC_Click(object sender, EventArgs e)
 162:     {
 163:         TFormaContato fc = new TFormaContato();
 164:         string script = "";
 165:  
 166:         fc.BindFromUI(this, this.GetType(), new ArrayList());
 167:         fc.ContatoId = Int32.Parse(tbxTContatoId.Text); //o único que deve ser setado manualmente
 168:         bool ok = (tbxTFormaContatoId.Text.Equals("") || tbxTFormaContatoId.Text.Equals("0")) ? fc.Insert() : fc.Update();
 169:  
 170:         script += Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(fc.MsgInfo), false);
 171:         script += ok ? "$dvDetFormaContato.jqmHide();" : "";
 172:         if (ok)
 173:         {
 174:             grdTContatoListaFormaContato.DataSource = TFormaContato.ListarPorContato(Int32.Parse(tbxTContatoId.Text));
 175:             grdTContatoListaFormaContato.DataBind();
 176:         }
 177:  
 178:         ScriptManager.RegisterStartupScript(this, this.GetType(), "salvafc", script, true);
 179:     }
 180:  
 181:     #endregion
 182:  
 183:     #region Modal de Tipos de Formas de Contato
 184:     protected void btnFiltrarTFC_Click(object sender, EventArgs e)
 185:     {
 186:         grdTipoFC.DataSource = TTpFormaContato.ListarTodos();
 187:         grdTipoFC.DataBind();
 188:     }
 189:  
 190:     protected void btnSalvaTFC_Click(object sender, EventArgs e)
 191:     {
 192:         TTpFormaContato tfc = new TTpFormaContato();
 193:         string script = "";
 194:  
 195:         tfc.BindFromUI(this, this.GetType(), new ArrayList());
 196:         bool ok = (tbxTTpFormaContatoId.Text.Equals("") || tbxTTpFormaContatoId.Text.Equals("0")) ? tfc.Insert() : tfc.Update();
 197:  
 198:         script += Consts.JavaScript.Alert(Consts.Funcoes.Replacer4js(tfc.MsgInfo), false);
 199:         script += ok ? "$dvDetTpFormaContato.jqmHide();" : "";
 200:         if (ok)
 201:         {
 202:             grdTipoFC.DataSource = TTpFormaContato.ListarTodos();
 203:             grdTipoFC.DataBind();
 204:             ddlTFormaContatoTpFormaContatoId.DataSource = TTpFormaContato.ListarTodos();
 205:             ddlTFormaContatoTpFormaContatoId.DataBind();
 206:         }
 207:  
 208:         ScriptManager.RegisterStartupScript(this, this.GetType(), "salvatfc", script, true);
 209:     }
 210:  
 211:     #endregion
 212: }

Vamos direto no que você reparou de diferente ;-)

No nosso código, temos um region chamado “Rotinas comuns a todos os botões de modais”. É isso mesmo! o código contido nela é comum a todos os modais! E olha só, são exatamente os botões Novo, Editar e Excluir de cada cadastro :-)

No CommandArgument da cada botão, eu passo o seguinte, através do #Bind: Nome da Classe, Chave do Registro (que é passado no primeiro parâmetro do #Bind) e o Nome do Modal que esta janela abre. Isto é feito formatando-se o resultado do comando #Bind, sendo que onde está o “{0}” será substituído pelo valor do primeiro parâmetro do comando #Bind, no nosso caso, o campo Id da tabela.

Notaram que todos estes botões apontam para UMA única rotina em seu evento OnClick (uma para cada ação: novo, editar e excluir)? Porém eles manipulam classes diferentes!

Pois é, classes diferentes, porém concebidas da mesma maneira!

Estudando o evento OnClick do botão Editar, vemos que ele separa cada argumento (que separei por vírgula) em um array de string, a nossa variável args.

Temos depois disso a primeira novidade: instanciamos um objeto em tempo de execução!

Para isso, faremos uso do namespace System.Runtime.Remoting e das classes ObjectHandle e Activator.

A primeira é uma classe que armazena referências de objetos, e a segunda cria-os, basicamente.

Em uma instância de ObjectHandle (variável clsCad), criamos em tempo de execução uma instância da classe que passamos no CommandArgument do botão Novo. Para isso, utilizamos o método estático CreateInstance da classe Activator, que na sobrecarga que utilizei pede como parâmetros o nome do assembly onde esta classe se encontra e o nome completo da classe (o namespace e o nome da classe) e retorna uma instância de ObjectHandle, que contém a referência deste objeto que criamos. No índice zero da variável args, gravamos o nome da classe que pegamos no CommandArgument e utilizamos neste método.

Em seguida, pegamos as informações de tipo da classe criada em uma instância de uma classe Type. Note que não usei o método GetType() da classe clsCad diretamente: Se eu fizesse isso, o método GetType() iria me retornar as informações da classe ObjectHandle, e não da classe de cadastro que instanciei, e que está encapsulada neste objeto.

Para pegar as informações do objeto encapsulado em si, chamo o método Unwrap() do objeto clsCad, que aí sim, temos o nosso objeto de cadastro à disposição, e a partir dele chamo o GetType().

Com isso, chamaremos os métodos de exibição e atribução dos valores na UI através do método InvokeMember do nosso objeto Type.

O método InvokeMember pede como parâmetros o nome do método em questão, os BindingFlags, que no nosso caso utilizamos BindingFlags.InvokeMethod, o Binder padrão, que no nosso caso utilizamos null, o objeto em que o método será chamado, onde utilizamos a nossa variável clsCad com o método Unwrap(), e um array de object contendo os parâmetros para o método a ser chamado.

No método SetByID(), passamos como parâmetro um array de object contendo as chaves primárias do registro a ser mostrado. Ele é obtido através do índice 1 da variável args.

O método BindToUI() pede como parâmetros a página em que estão os controles a ser atribuídos, as informações de seu tipo e um arraylist indicando quais controles não serão atribuídos.

Para usar o BindToUI, necessitamos nomear cada componente seguindo a convenção: Prefixo de 3 letras, Nome da Classe e Nome da Propriedade.

Feito tudo isso, registramos um JavaScript com o comando para abrir a janela modal referente ao cadastro; janela esta que é passado no terceiro item da variável args.

Notem que TODAS as classes trabalham da mesma forma. Esta maneira de trabalhar e as convenções adotadas foi o que permitiu que escrevessemos um só trecho de código para quatro classes distintas.

Os botões Novo e Excluir trabalham da mesma maneira. A difereça entre eles é:

No botão Novo, criamos um ArrayList para não atribuirmos valor no combo-box de tipos de forma de contato do Cadastro de Formas de Contato de cada contato, pois como é inicializado um objeto SEM DADOS, o valor inicializado na propriedade correspondente possui algo que não existe no combo-box, e isso ocasiona um erro de execução.

No botão Excluir, após executarmos o método Delete() (dinamicamente!), pegamos o valor da propriedade MsgInfo através de um objeto PropertyInfo (que vimos anteriormente) e disparamos para o usuário.

Nos botões de Salvar temos as particularidades de cada classe, como o “refresh” dos grids e alguns campos de chave estrangeira que são atribuídos manualmente, sendo os outros atribuídos via método BindFromUI.

E por fim, terminamos a interface Web e fechamos a exemplificação dos métodos novos mais importantes da nova Classe de Conexão, e no próximo post tecerei algumas conclusões sobre o assunto.

Projeto de Exemplo da Classe de Conexão – Simple PIM (263 kB)

Um abraço!

0 comentários:


Postar um comentário

Para tornar este artigo ainda mais interessante, escreva suas críticas (desde que construtivas e sem ofenças), elogios, sugestões, complementos, dúvidas, etc, etc, etc!!!

  © Blogger templates ProBlogger Template by Ourblogtemplates.com 2008 - Editado e configurado por Leonel F.

Voltar ao TOPO