Skip Navigation Links



Translate this page now :



»Programação
»Programação.NET
»Banco de Dados
»Webdesign
»Office
» Certificações Microsoft 4
»Treinamentos4
»Programação 4
»Webdesign«
»Office & User Tips«
»Grupos de UsuĆ”rios
»CĆ©lulas AcadĆŖmicas«
intcontpiada : 118
Problema de BIOS
Você já está cadastrado e participa do grupo de usuários de sua cidade ? Se não, comente o porque.
 
 
FaƧa um pequeno teste com 10 questƵes de VB
.:.
Teste seus conhecimentos em Visual Basic, SQL Server e ASP 3.0 com nossas provas on-line
.:.
Aprimore seus conhecimentos em programaĆ§Ć£o com nosso treinamento on-line de lĆ³gica de programaĆ§Ć£o
.:.
Veja nosso calendƔrio de treinamentos
Gostou da PƔgina?
Então

para um amigo!

Pesquisa personalizada
Pesquisar Dicas:

 







Gerando mapas de site para o ASP.NET

O ASP.NET possui um novo e poderoso recurso, que é a geração de mapas de sites. Vocês podem ler mais sobre esse recurso em http://www.bufaloinfo.com.br/artigos/coluna28.asp

Porém, como vocês lerão, não existe nenhum recurso, nenhum wizard, que simplifique a montagem do XML para ser utilizado como mapa de site.

Não gosto de deixar nada incompleto. Escrevi sobre a criação de mapas de sites, mas ter que escrever o XML manualmente, na era em que estamos de desenvolvimento web, é impensável. Então vou nesse artigo demonstrar a criação de uma aplicação windows com o objetivo de gerar automaticamente o mapa do site, a partir de simples configuração.

Precisaremos de uma Treeview para exibir o novo mapa do site de forma hierárquica e também precisaremos de um pequeno cadastro para adicionar novos nós.

Na versão anterior, utilizariamos um splitter para dividir a tela em 2. Na nova versão temos um objeto chamado splitcontainer que substitui o splitter, já trazendo um panel em cada um dos seus lados.

É verdade que o splitcontainer simplifica o trabalho de uso de um splitter, trazendo as configurações mais simples em termos de panels já prontas. Porém fico em dúvida se um splitcontainer será tão flexivel como o antigo splitter. Não consegui, por exemplo, fazer com que o foco iniciasse em uma textbox do 2o panel. Mas lembrem-se : Estamos trabalhando com uma versão beta, muita coisa vai melhorar até a versão final.

Em uma das metades do splitcontainer vamos inserir uma treeview, na outra, um pequeno cadastro no qual precisaremos dos campos "Titulo", "URL" e "Descrição" e dois botões, "Gravar" e "Alterar".

Precisaremos tabém de um menu na aplicação. Veja como ele ficará :

Não vou inserir as informações do cadastro diretamente no treeview. Se assim fizesse teria depois o trabalho de gerar o XML "manualmente". Vamos sim gerar um dataSet com a estrutura do mapa do site para que possamos inserir nele os dados cadastrados e obter como resultado o XML de mapa do site automaticamente.

Veja o XML de mapa do site que deveremos gerar :

<siteMap>
<siteMapNode title="Home" description="Página principal" url="home.aspx">
<siteMapNode title="A Empresa" description="Informações sobre a empresa" url="empresa.aspx">
<siteMapNode title="Filiais" description="Informações sobre filiais" url="filiais.aspx" />
</siteMapNode>
<siteMapNode title="Produtos" description="Informações sobre produtos" url="produtos.aspx">
<siteMapNode title="Eletrodomésticos" description="Eletrodomésticos" url="eletro.aspx" />
<siteMapNode title="Móveis" description="Móveis" url="moveis.aspx" />
</siteMapNode>
</siteMapNode>
</siteMap>

Como vocês podem observar, a estrutura é hierárquica. Então como colocar isso em um dataSet ?

A dúvida surge devido a visão normalmente relacional do dataSet. Porém, por mais que normalmente nos limitemos a fazer o dataSet espelhar dados relacionais, ele é em seus fundamentos um objeto para manipulação de XML e, consequentemente, hierárquico. Já fizemos isso antes : No artigo em .... utilizamos uma estrutura semelhante para fazer a geração de documentos RSS a partir de um DataSet.

Comparando com a visão relacional, isso é na verdade um dataSet chamado siteMap que contém uma tabela chamada siteMapNode e esta contém um auto-relacionamento, ligando registros da tabela siteMapNode com outros também da siteMapNode. Mas é possível fazer um relacionamento sem chaves (reparem que a diferença entre a estrutura hierárquica do XML e a estrutura relacional e a ausência de chaves de ligação, não são necessárias) ?

Sim, é possível, mas como vocês verão não estaremos totalmente "sem chaves". Então vamos por mãos a obra.

Precisamos adicionar um novo dataSet em nossa aplicação. Porém temos um problema : O novo editor de dataSets no Visual Studio 2005 é diferente do editor de XML, não possui mais a flexibilidade de edição de um schema. Desta forma se utilizarmos Add New Item e pedirmos para adicionar um dataSet não conseguiremos chegar ao resultado desejado.

Precisamos então utilizar o add new item mas pedir para adicionar um XML Schema e não um dataSet. Adicionando um XML Schema teremos a liberdade de editar o schema mais a vontade, apesar de que mesmo com esta opção não temos mais como visualizar o XML, como faziamos livremente no Visual Studio 2003.

Vamos utilizar a toolbox para adicionar elementos em nosso schema. Ao invés de criar um Element, representando uma tabela, faremos um ComplexType. Um ComplexType é como definirmos um "tipo de tabela", sem definirmos a tabela em si, apenas o tipo.

Vamos chamar o complexType de siteMapNode, precisa ser assim, identico em maiúsculas e minúsculas, para que o XML seja gerado desta forma e assim compreendido pelo ASP.NET

Vamos inserir os seguintes campos : title, description e url. Todos os 3 como string. Observe que ao lado dos campos aparece a letra "E". Isso significa que no XML cada campo será um elemento contendo seu valor.

Porém não é isso que precisamos : No XML usado pelo ASP.NET esses 3 campos são atributos, não elementos. Então clique na letra "E", surgira uma combo que permitirá você troca-la. Selecione a opção Attribute, a letra "E" será trocada pela letra "A", indicando que os campos passarão a ser guardados como atributos, porém isso não afetará o dataset.

Vamos então adicionar um campo a mais. Esse campo a mais se chamará siteMapNode e o tipo deste campo a mais será siteMapNode, isso mesmo, será do tipo do nosso complexType.

Desta forma estamos informando que dentro de nosso complexType podemos ter diversas estruturas repetitivas de siteMapNode, infinitamente.

Feita essa definição, agora sim vamos inserir um Element. No tipo do Element (espaço ao lado do nome), indique o tipo siteMapNode. Agora sim, criamos um elemento do tipo de nosso complexType, concluindo a tarefa de criação do DataSet.

Por fim, vamos abrir a janela de propriedades e definir a propriedade targetNamespace com o valor http://schemas.microsoft.com/AspNet/SiteMap-File-1.0 . Este é o nome dado a linguagem de siteMaps criada pela MS, colocando este nome em nosso targetNamespace ficará bem simples a gravação e recuperação de arquivos de siteMaps. O nome precisa ser identico ao que está ai, inclusive maiusculas e minusculas.

Porém quando inserimos esse arquivo no projeto selecionamos um XML Schema. Assim sendo este arquivo ainda não é um dataSet. Para que este arquivo seja interpretado como um dataSet precisamos que seja processado pela CustomTool do Visual Studio para processamento do dataSet. Assim sendo precisamos selecionar o arquivo no solution explorer, abrir a janela de propriedades e em "Custom Tool" digitar MSDataSetGenerator.

Uma custom tool é uma ferramenta pertencente ao Visual Studio, uma espécie de addIn, que se agrega a arquivos do projeto gerando algum processamento adicional para os arquivos aos quais eles encontram-se vinculados. A Custom Tool identifica sempre que este arquivo sofrer algum tipo de alteração e refaz o processamento.

O DataSet é um dos principais exemplos disso. Não basta o dataSet ser montado em formato XML, é necessário que ele seja compreendido como uma nova classe na aplicação. Por isso essa custom tool gera um arquivo de código - .vb - a partir do arquivo de schema de um novo dataset. O arquivo contém a codificação da nova classe dataSet - em nosso caso siteMap - que será utilizada pela aplicação. Você pode visualizar este código se pedir para ver os arquivos ocultos no solution explorer.

Outro exemplo de caso em que uma custom tool é utilizada é na adição de uma web Reference, que também gera um arquivo de código .vb

 

Vamos então inserir um dataSet no form. Simplesmente selecionando o dataSet na toolbox e inserindo no form é mostrada uma tela perguntando qual será o tipo do dataset, sendo que siteMap aparecerá como uma das opções, a que escolheremos.

Vamos agora codificar o botão "Adicionar". Fazendo isso muitas dúvidas sobre o uso deste dataSet serão solucionadas.

Antes do código propriamente, vamos acertar alguns detalhes :

Precisamos adicionar um nó inicial na treeview. Vamos chamar esse nó de site.

  • O botão adicionar precisará estar desabilitado por default. Apenas deverá ser habilitado quando um elemento for selecionado na treeview. Vamos desabilita-lo e faremos em seguida o código para habilita-lo quando houver uma seleção.
  • Cada elemento terá uma chave (sim, uma chave primária). Vamos guardar essas chaves na propriedade tag do objeto treenode. O treenode que definimos inicialmente ("site") ficará com a chave 0, não esqueça de fazer essa atribuição em design.
  • Vamos assumir que não poderemos ter mais de uma página principal abaixo de site. Assim sendo, abaixo de site teremos um único treenode, abaixo deste sim toda uma hierarquia do site.

A propriedade tag é uma propriedade existente em ambiente Windows há muito tempo, desde versões muito antigas do VB.

Todo controle windows tem propriedade tag, mas ela não faz absolutamente nada. O fato desta propriedade não fazer nada nos permite guardar valores nesta propriedade. Assim podemos guardar qualquer valor na propriedade tag e recupera-lo posteriormente, mantendo a ligação do valor com o objeto ao qual se refere, é isso que estamos fazendo aqui com a chave primária.

 

O código do botão adicionar precisará fazer as seguintes tarefas :

  • Verificar se a tag do nó selecionado é 0. Se for e já houver mais de um nó na treeview, impedir a adição : Só pode haver um nó principal abaixo de "Site".
  • Somar +1 na chave primária (contador)
  • Criar um novo registro na tabela siteMapNode
  • Preencher os dados (description, url, title)
  • Preencher a chave primária
  • Se o nó selecionado não for o principal ("Site"), preencher a chave estrangeira
  • Criar um novo TreeNode
  • Gravar o registro na tabela
  • Preencher o text do treenode
  • Preencher o tag do treenode com a chave primária
  • Inserir o treenode na treeview
  • Limpar as caixas de texto
  • Expandir todos os nós da treeview

Mas na descrição acima foram citadas várias vezes as chaves primária e estrangeira, mas nós não temos isso no nosso dataSet!

Ai está o segredo : Nós temos as chaves ! As chaves são absolutamente necessárias para que nossa classe siteMap entenda a estrutura dos dados sem que tenhamos que manipular XML diretamente. Sabendo disso, a custom tool que criou essa classe automaticamente para nós também criou as chaves.

A chave primária do registro passou a se chamar siteMap_ID enquanto que a chave estrangeira, que indica a que outro registro ele encontra-se ligado, passou a chamar-se siteMap_ID_0 . Existe um padrão através do qual esses nomes podem ser identificados, mas havendo dúvidas você pode pedir para ver os arquivos ocultos, no solution explorer, abrir o arquivo .VB e buscar as chaves, procurando pelo trecho de código em que é criado o objeto relation.

Ok, então temos as chaves. Vamos então preenche-las. como ? Vamos manter um contador, uma variável a nível de classe, para gerar a chave primária. Já a chave estrangeira vai ser preenchida com o tag do treenode que está selecionado (que será o pai do novo elemento).

Veja como fica o código :

   49     Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles trvMap.AfterSelect

   50 

   51 

   52         cmdAdicionar.Enabled = True

   53 

   54     End Sub




   46         Dim linha As siteMap.siteMapNodeRow

   47 

   48         If trvMap.SelectedNode.Tag = 0 And trvMap.Nodes.Count > 1 Then

   49 

   50 

   51             MsgBox("Apenas pode haver uma página principal")

   52             Exit Sub

   53         End If

   54 

   55         indiceNo += 1

   56 

   57         linha = SiteMap1.siteMapNode.NewsiteMapNodeRow

   58 

   59 

   60         linha.description = txtdescricao.Text

   61         linha.url = txtUrl.Text

   62         linha.title = txtTitulo.Text

   63         linha("sitemapnode_id") = indiceNo

   64 

   65         If trvMap.SelectedNode.Tag <> 0 Then

   66             linha("sitemapnode_id_0") = trvMap.SelectedNode.Tag

   67 

   68 

   69         End If

   70 

   71         CriarNo(trvMap.SelectedNode, linha)

   72 

   73         SiteMap1.siteMapNode.Rows.Add(linha)

   74 

   75 

   76         limparCaixas()

   77         trvMap.ExpandAll()

Observe que dois trechos de código foram transformados em rotinas separadas : A criação de um nó na treeView e a limpeza das caixas de texto. Isso é algo intuitivo, gerando essas subs de forma a garantir que essas tarefas sejam centralizadas e não duplicadas durante o código. De fato, a necessidade da sub CriarNo só percebi após ter chegado quase ao fim do código.

Se teorizarmos, provavelmente descobriremos que este ato intuitivo esteja ligado a alguma regra de refactoring. Mas procurar tornar este tipo de codificação intuitiva deve ser o objetivo de todo desenvolvedor.

Veja como ficam as rotinas :

   86     Private Sub limparCaixas()

   87         txtTitulo.Text = ""

   88         txtdescricao.Text = ""

   89         txtUrl.Text = ""

   90 

   91         txtTitulo.Focus()

   92     End Sub

   93 

   94     Private Function CriarNo(ByVal noPai As TreeNode, ByVal linha As DataRow) As TreeNode

   95 

   96 

   97         Dim trno As TreeNode

   98         trno = New TreeNode

   99         trno.Text = linha("title")

  100         trno.Tag = linha("sitemapnode_id")

  101         noPai.Nodes.Add(trno)

  102         Return (trno)

  103     End Function

Controle de alterações

Vamos adicionar na aplicação um mecanismo de segurança : Se o usuário pedir para sair da aplicação e houverem alterações não salvas no mapa vamos interroga-lo se deseja realmente sair da aplicação.

Para isso basta programar o evento closing do form, veja como fica :

  105     Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

  106 

  107 

  108         If SiteMap1.HasChanges Then

  109             Dim resp As MsgBoxResult

  110             resp = MsgBox("Existem alterações no mapa, tem certeza de que deseja sair ?", MsgBoxStyle.Exclamation Or MsgBoxStyle.DefaultButton2 Or MsgBoxStyle.YesNo, "Tem certeza ?")

  111 

  112 

  113 

  114             If resp = MsgBoxResult.No Then

  115                 e.Cancel = True

  116             End If

  117         End If

  118     End Sub

Drag-And-Drop

A propria estrutura das informações já nos sugere a realização de Drag-And-Drop. O usuário certamente vai desejar arrastar nós para outra posição, corrigindo a hierarquia do site.

Então vamos fazer a programação de eventos de drag-and-drop da treeview. Devemos começar com a programação do evento itemDrag, no qual aprovaremos a realização do drag-and-drop.

Feito isso programamos o evento dragEnter, aceitando o objeto e o evento dragdrop, realizando a transferência.

No dragdrop precisaremos retirar o nó arrastado de dentro da Treeview e inseri-lo em sua nova posição. Precisaremos também localizar esse registro no dataSet e alterar a chave estrangeira, indicando qual é o novo nó pai do que foi arrastado. Observe no código que não permitiremos que um nós seja arrastado para "Site", gerando a duplicação de páginas iniciais do site.

  121     Private Sub trvMap_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles trvMap.DragEnter

  122 

  123 

  124 

  125         e.Effect = e.AllowedEffect

  126     End Sub

  127 

  128     Private Sub trvMap_ItemDrag(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemDragEventArgs) Handles trvMap.ItemDrag

  129 

  130 

  131 

  132         If e.Button = Windows.Forms.MouseButtons.Right Then

  133 

  134 

  135             DoDragDrop(e.Item, DragDropEffects.Move)

  136         End If

  137     End Sub

  138 

  139     Private Sub trvMap_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles trvMap.DragDrop

  140 

  141 

  142 

  143         Dim p As New Point(e.X, e.Y)

  144         Dim tndrop As TreeNode

  145         Dim tn As TreeNode

  146 

  147         p = trvMap.PointToClient(p)

  148         tndrop = trvMap.GetNodeAt(p)

  149 

  150         If Not IsNothing(tndrop) AndAlso tndrop.Tag <> 0 Then

  151 

  152 

  153             tn = e.Data.GetData(GetType(TreeNode))

  154             trvMap.Nodes.Remove(tn)

  155             tndrop.Nodes.Add(tn)

  156 

  157             Dim dr As siteMap.siteMapNodeRow

  158             dr = SiteMap1.siteMapNode.Rows.Find(tn.Tag)

  159 

  160             dr.BeginEdit()

  161             dr("sitemapnode_id_0") = CType(tndrop.Tag, Integer)

  162 

  163             dr.EndEdit()

  164             trvMap.ExpandAll()

  165         End If

  166     End Sub

No evento DragDrop foi necessário fazer uso de alguns recursos gráficos para encontrar o nó destino, para o qual está sendo feito o drop. Obtivemos o ponto de tela no qual o objeto foi soltado, utilizamos o método PointToClient para converte-lo para um ponto na TreeView e finalmente o GetNodeAt para obtermos o objeto TreeNode.

Para a edição da chave estrangeira um simples Find nos levou até a linha que deveria ser editada. Observe que o nó de origem é transmitido do evento ItemDrag para o evento DragDrop através da chamada do DoDragDrop. O treenode chega na propriedade Data do objeto "e" e é recuperado pelo método GetData.

 

Alteração

Para deixar a aplicação flexivel precisaremos também permitir a alteração de dados dos nós. Para que o usuário possa alterar um nó, vamos utilizar o duplo clique. Assim o usuário faz duplo clique em um nó para entrar em modo de alteração deste nó.

Quando isso acontecer precisaremos desabilitar o botão adicionar, habilitar o botão o botão Alterar e preencher as caixas de texto.

  169     Private Sub trvMap_NodeMouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) Handles trvMap.NodeMouseDoubleClick

  170 

  171 

  172 

  173         Dim tn As TreeNode

  174 

  175         tn = e.Node

  176         If Not IsNothing(tn) AndAlso tn.Tag <> 0 Then

  177             Dim dr As siteMap.siteMapNodeRow

  178 

  179             dr = SiteMap1.siteMapNode.Rows.Find(tn.Tag)

  180             txtdescricao.Text = dr.description

  181             txtUrl.Text = dr.url

  182             txtTitulo.Text = dr.title

  183             cmdAdicionar.Enabled = False

  184             cmdAlterar.Enabled = True

  185             tnAlterando = tn

  186         End If

  187     End Sub

  188 

  189 

  190     Private Sub cmdAlterar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAlterar.Click

  191 

  192 

  193         Dim dr As siteMap.siteMapNodeRow

  194 

  195         dr = SiteMap1.siteMapNode.Rows.Find(tnAlterando.Tag)

  196 

  197 

  198         dr.BeginEdit()

  199         dr.title = txtTitulo.Text

  200         dr.url = txtUrl.Text

  201         dr.description = txtdescricao.Text

  202         dr.EndEdit()

  203 

  204         limparCaixas()

  205         cmdAlterar.Enabled = False

  206         cmdAdicionar.Enabled = True

  207     End Sub

Salvar

Vamos agora criar a possibilidade de salvar o conteúdo do dataSet em um arquivo XML para ser utilizado no ASP.NET

Precisaremos inserir um objeto SaveFileDialog para poder interrogar o usuário sobre com que nome deseja salvar o arquivo. Estes objetos dialog nos permitem fazer uso de janelas de dialogo pré-definidas pelo sistema operacional, mantendo nosso sistema integrado com o SO.

Devemos configurar a propriedade Filter para indicar os tipos de arquivo que estaremos podendo salvar, após isso o objeto está pronto para ser usado. Veja como fica o Filter :

Documentos XML (*.xml)|*.xml|Mapa de site (*.sitemap)|*.sitemap

Desta forma a caixa de dialogo para salvar permitirá salvarmos o arquivo com a extensão XML ou já com a extensão sitemap, que é a extensão esperada pelo ASP.NET

No código, após perguntar o nome do arquivo usaremos writeXML do dataSet para gravar o dataSet em disco como XML. O fato de termos configurado o targetNamespace do dataSet exatamente com o nameSpace dos siteMaps deixa essa tarefa bem simples. Apenas precisaremos garantir que o schema não seja gravado junto.

Outra questão interessante são os menus, Salvar e Salvar Como. O menu Salvar deverá ser habilitado apenas quando houverem alterações a serem salvas. Já o menu Salvar Como deverá estar habilitado sempre. O menu Salvar apenas perguntará o nome do arquivo se este já não tiver um nome. Se o arquivo houver sido aberto e desta forma já possuir um nome, o menu Salvar não pergunta o nome, apenas salva o arquivo.

veja como fica o código :

  210     Private Sub mnuSalvarComo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuSalvarComo.Click

  211 

  212 

  213         SalvarArquivo()

  214     End Sub

  215 

  216     Private Sub mnuSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuSalvar.Click

  217 

  218 

  219         GravarArquivo()

  220     End Sub

  221 

  222     Private Sub SalvarArquivo()

  223         If SD.ShowDialog() = Windows.Forms.DialogResult.OK Then

  224             nomeArquivo = SD.FileName

  225             GravarArquivo()

  226             MsgBox("Arquivo Gravado!", MsgBoxStyle.Information, "Gravado!")

  227 

  228 

  229         End If

  230     End Sub

  231 

  232 

  233     Private Sub GravarArquivo()

  234         If nomeArquivo = "" Then

  235             SalvarArquivo()

  236         Else

  237             SiteMap1.WriteXml(nomearquivo, XmlWriteMode.IgnoreSchema)

  238 

  239 

  240             SiteMap1.AcceptChanges()

  241         End If

  242     End Sub

Observe o uso do AcceptChanges : com isso fazemos um "reset" nos status dos registros do dataset, para que a mensagem do evento closing não seja provocada caso o usuário feche a aplicação, afinal, neste momento não existem informações alteradas no mapa do site.

Abrir

Para abrir o arquivo precisaremos utilizar o OpenFileDialog, ao invés do SaveFileDialog. Da mesma forma, configuraremos a propriedade Filter exatamente como fizermos no caso do SaveFileDialog.

Bastará utilizarmos o ReadXML do objeto dataSet para lermos o arquivo XML. Mas após a leitura precisaremos atualizar o valor do contador da chave primária, para garantir que a edição do arquivo seja feita corretamente.

Feito isso teremos um problema adicional : Preencher a treeview com as informações que acabamos de ler. Como se trata de uma árvore hierárquica precisaremos utilizar recursividade para realizar o preenchimento, o código fica bem interessante.

Veja como fica o código :

  245     Private Sub mnuAbrir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuAbrir.Click

  246 

  247 

  248         abrirArquivo()

  249         preencherTree()

  250     End Sub

  251 

  252     Private Sub abrirArquivo()

  253         If OD.ShowDialog = Windows.Forms.DialogResult.OK Then

  254 

  255 

  256             SiteMap1.ReadXml(OD.FileName)

  257             SiteMap1.AcceptChanges()

  258             nomeArquivo = OD.filename

  259             indiceNo = SiteMap1.siteMapNode.Compute("max(sitemapnode_id)", "")

  260 

  261 

  262         End If

  263     End Sub

Observe que o evento click do menu abrir além de chamar a sub para abertura do arquivo também chama uma sub para o preenchimento da TreeView. A sub preencherTree faz o primeiro passo no preenchimento, veja :

  265     Private Sub preencherTree()

  266         Dim trno As New TreeNode

  267         trvMap.Nodes.Clear()

  268         trno.Text = "Site"

  269         trno.Tag = 0

  270         trvMap.Nodes.Add(trno)

  271         SiteMap1.siteMapNode.DefaultView.RowFilter = "sitemapnode_id_0 is null"

  272 

  273 

  274         ConverterLinhasNos(trno, SiteMap1.siteMapNode.DefaultView)

  275 

  276         trvMap.ExpandAll()

  277     End Sub

Todo o conteúdo da Treeview é eliminado, o nó inicial, "Site", é recriado e é chamado o método ConverterLinhasNos, tendo como parâmetro o nó inicial (que será pai de todos) e uma dataView. Este método é recursivo, como veremos a seguir. Por fim, quando o processamento terminar, toda a treeview já estará preenchida, então simplesmente fazemos um ExpandAll para exibir todos os nós.

Observe que foi colocado um RowFilter na DataView antes de passa-la para o método ConverterLinhasNos. Estamos fazendo a primeira chamada, o objetivo é preencher os filhos do nó "Site" e estes tem o campo sitemapnode_id_0 como null, dai o RowFilter para inicialmente localizar apenas estas linhas.

Veja como fica o código do ConverterLinhasNos :

  279     Private Sub ConverterLinhasNos(ByVal noPai As TreeNode, ByVal dv As Data.DataView)

  280 

  281 

  282         Dim dr As DataRowView

  283         For Each dr In dv

  284             Dim linhasFilho As DataView

  285             Dim trno As TreeNode

  286             trno = CriarNo(noPai, dr.Row)

  287             linhasFilho = dr.CreateChildView("siteMapNode_siteMapNode")

  288 

  289 

  290             If linhasFilho.Count > 0 Then

  291                 ConverterLinhasNos(trno, linhasFilho)

  292             End If

  293         Next

  294     End Sub

É necessário processar cada linha da DataView, inserindo os elementos no treeNode pai. Para a inserção dos elementos reaproveitamos aqui a função CriarNo. Fica então explicado porque foi criada como função e não como sub.

Para cada elemento da dataView é necessário descobrir se o elemento possui nós filhos ou não. Para isso utilizamos o método CreateChildView. Este método, existente em objetos do tipo DataRowView - linhas de dataView, recebe como parâmetro o nome de um DataRelation e nos devolve uma nova dataView apenas com os registros filhos desta linha. Então se houverem registros filhos (count>0) precisamos adiciona-los no treeview, como filhos do nó que acabamos de criar. É neste ponto que esta sub se torna recursiva, chamando novamente ela mesma. Observe que o nível de recursividade é indeterminado, será tantos quantos forem os níveis de nós filhos.

Conclusão

Com minha experiência em .NET 1.1, foi necessário muito pouco estudo específico para poder criar esta aplicação em .NET 2.0 . Isso é uma ótima demonstração de como será fácil a passagem da versão 1.1 para a versão 2.0

Também é importante observar como ficou mais difícil realizar uma tarefa um pouco fora de padrões comuns, como observamos com a criação de nosso dataSet. Assim sendo, quem não tiver experimentado situações assim no .NET 1.1 terá muita dificuldade de entender esse mecanismo e aproveitar-se dele no .NET 2.0. Vemos então a importância do estudo do .NET 1.1

Também é importante destacar que todo o ambiente de desenvolvimento da versão 2.0 está repleto de pequenas melhorias que geram aumento de produtividade no desenvolvimento, mas algumas coisas são tão sutis que chegam a passar despercebidas quando se está envolvido com o desenvolvimento. Por exemplo, ao trocar uma sub por function o end sub vira end function automaticamente. Isso passará despercebido ao desenvolvedor, o que será notado depois será a produtividade final do desenvolvimento.

 

Dennes Torres
MCAD,MCSD,MCSE,MCDBA





Envie seus comentįrios sobre este artigo

Nome :

E-mail :

Comentários :


Avise-me quando houverem novos comentįrios nesta pįgina

Veja abaixo os comentários já enviados :

Nome : Roger E-Mail : erogennin@gmail.com
Oi Dennes,
Essa dica funciona também no Visual Studio 2008?
Nome : None E-Mail : prpc@chef.net
PRPhonecards these is rechargeable phone cards and long distance phone cards online.
Nome : E-Mail :
-1'
Nome : E-Mail :
Nome : Marcelo Martins E-Mail : marceloatmartins@gmail.com
Olá Dennes,
Gostei muito do seu artigo, de facto é impensável não existir uma ferramenta para gerar o sitemap, entretanto tentei fazer o seu exemplo de aplicativo no VS 2010 e não consegui criar ComplexType e seu Atributos. Acho que o componente evoluiu e não é como está no seu exemplo. Por acaso voce irá atualizar ?
Abs
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : q151ZA7C E-Mail : pdcbm9t5yn@yahoo.com
mmcasetti > Yes, I remember you. I think that Ia0see mutpille point of entry :1. Start a documentation infrastructure in the code itself (not on the wiki) using standard documentation stuff in python2. Start a branch to port to Python3/GTK33. Play with it and profile it to improve performance.4. Write/improve example codes.I think that those are ways to start contributing
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : adidas ultra boost E-Mail : ssqxiuvr@gmail.com
I wanted to write down a quick comment to express gratitude to you for some of the marvelous steps you are sharing here. My rather long internet investigation has finally been compensated with awesome suggestions to share with my partners. I would express that we readers actually are definitely fortunate to exist in a good site with so many wonderful individuals with interesting plans. I feel very blessed to have encountered the web site and look forward to some more cool times reading here. Thanks once again for everything.
adidas ultra boost https://is.gd/iFnsJs

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Conheça mais sobre o nosso site :

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::



Quer saber mais?
Faça um curso na Búfalo Informática, Treinamento e Consultoria e
Prepare-se para o Mercado!
Veja o que a Búfalo tem para você.

ļæ½ BĆŗfalo InformĆ”tica, Treinamento e Consultoria - Rua Ɓlvaro Alvim, 37 Sala 920 - CinelĆ¢ndia - Rio de Janeiro / RJ
Tel.: (21)2262-1368 (21) 9240-5134 (21) 9240-7281 e-Mail:
contato@bufaloinfo.com.br