<rss version="2.0" xmlns:a10="http://www.w3.org/2005/Atom"><channel><title>Dicas Técnicas BufaloInfo</title><link>http://www.bufaloinfo.com.br/</link><description>Dicas Técnicas Produzidas pela Búfalo Informática</description><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1024</link><title>ASP.NET : Resolvendo o Problema do www e Aumentando o PageRank</title><description>&lt;br&gt;Para conseguir sucesso na web nossos sites precisam ser localizaveis atrav&amp;#233;s das ferramentas de busca. &lt;br&gt;&lt;br&gt;Para conseguirmos isso nosso site depende do c&amp;#225;lculo de pagerank que &amp;#233; realizado pelas ferramentas de busca. O pagerank &amp;#233; atribuido para nosso site e cada uma de suas p&amp;#225;ginas de acordo com os links que recebermos de outros sites.&lt;br&gt;&lt;br&gt;Por&amp;#233;m pequenos problemas de nomenclatura do site, chamados de problemas de canonicaliza&amp;#231;&amp;#227;o, podem fazer com que o pagerank do site seja dividido, reduzindo o ranking do seu site.&lt;br&gt;&lt;br&gt;O caso cl&amp;#225;ssico &amp;#233; do uso &amp;quot;www&amp;quot;. Nosso site frequentemente pode ser acessado com ou sem &amp;quot;www&amp;quot; : http://www.nossosite.com.br ou http://nossosite.com.br&lt;br&gt;&lt;br&gt;Pegando o caso do &amp;quot;www&amp;quot; como exemplo, podemos corrigir isso em aplica&amp;#231;&amp;#245;es ASP.NET utilizando o Global.Asax&lt;br&gt;&lt;br&gt;Para isso podemos programar o evento Application_BeginRequest e, se a URL contiver o &amp;quot;www&amp;quot;, podemos redirecionar para a URL sem &amp;quot;www&amp;quot;, por&amp;#233;m fazendo isso com o cuidado de avisar ao client (que pode ser uma ferramenta de busca) que ocorreu uma mudan&amp;#231;a permanente de endere&amp;#231;o.&lt;br&gt;&lt;br&gt;Feito isso, a ferramenta de busca saber&amp;#225; que refer&amp;#234;ncias ao nosso site com e sem o &amp;quot;www&amp;quot; significam a mesma coisa.&lt;br&gt;&lt;br&gt;Veja como fica o c&amp;#243;digo no global.asax :&lt;br&gt;&lt;br&gt;  protected void Application_BeginRequest(Object sender, EventArgs e)&lt;br&gt;&lt;br&gt;    {&lt;br&gt;     &lt;br&gt;        if (HttpContext.Current.Request.Url.ToString.ToLower().Contains(&amp;quot;http://www.mysite.com&amp;quot;))&lt;br&gt;&lt;br&gt;        {&lt;br&gt;            HttpContext.Current.Response.Status=&amp;quot;301 Moved Permanently&amp;quot;;&lt;br&gt;&lt;br&gt;            HttpContext.Current.Response.AddHeader(&amp;quot;Location&amp;quot;,Request.Url.ToString.ToLower().Replace(&amp;quot;http://www.mysite.com&amp;quot;,&amp;quot;http://mysite.com&amp;quot;));&lt;br&gt;&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;&lt;br&gt;Observe o uso do status 301 e do Header &amp;quot;Location&amp;quot; para indicar o endere&amp;#231;o correto do site&lt;br&gt;&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1017</link><title>ASP.NET : Configurando o page_error centralizado com Nested Master pages</title><description>&lt;br&gt;Em uma dica anterior (http://www.bufaloinfo.com.br/dicas.asp?cod=1009 ) mostrei como fazer um tratamento geral de erros para o site utilizando master pages. Por&amp;#233;m nada &amp;#233; t&amp;#227;o simples.&lt;br&gt;&lt;br&gt;Quando utilizamos nested master pages o problema se complica, pois a solu&amp;#231;&amp;#227;o que apresentei na dica anterior apenas far&amp;#225; com que a 2a master page tenha tamb&amp;#233;m o tratamento de erro da primeira, mas o page_Error da p&amp;#225;gina n&amp;#227;o estar&amp;#225; executando o tratamento de erro.&lt;br&gt;&lt;br&gt;A op&amp;#231;&amp;#227;o perfeita seria se na nested master page fosse poss&amp;#237;vel pegarmos o endere&amp;#231;o da rotina ligada ao seu page_Error e atribuirmos esse endere&amp;#231;o ao page_error da p&amp;#225;gina que usar&amp;#225; a nested master page. Por&amp;#233;m isso exigiria um volume de uso de reflection muito grande e como os provedores normalmente trabalham com medium trust, n&amp;#227;o funcionaria.&lt;br&gt;&lt;br&gt;A solu&amp;#231;&amp;#227;o para o problema &amp;#233; que a rotina que faz o tratamento do page_Error na master page seja definida como public e desta forma a nested master page poder&amp;#225; vincular esta rotina com o evento page_Error da p&amp;#225;gina que vir&amp;#225; a usar a nested master page -&amp;gt; a content page&lt;br&gt;&lt;br&gt;Realmente esta solu&amp;#231;&amp;#227;o cria um certo acoplamento entre as master pages, mas evita o reflection em excesso que exigiria full trust para o site. &lt;br&gt;&lt;br&gt;Na nested master page, o c&amp;#243;digo fica assim : &lt;br&gt;&lt;br&gt;    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load&lt;br&gt;        AddHandler Page.Error, AddressOf DirectCast(Me.Master, Bufalo).Page_Error&lt;br&gt;    End Sub&lt;br&gt;&lt;br&gt;Observe a necessidade do directCast em Me.Master para que a rotina Page_Error fique acess&amp;#237;vel.&lt;br&gt;&lt;br&gt;Ent&amp;#227;o temos :&lt;br&gt;&lt;br&gt;A master page principal define o page_error como p&amp;#250;blico&lt;br&gt;&lt;br&gt;No load da master page principal o page_Error &amp;#233; atribuido ao page_error de quem usar esta master page&lt;br&gt;&lt;br&gt;A nested master page utiliza a master page principal (e consequentemente ganha o page_error)&lt;br&gt;&lt;br&gt;A nested master page, em seu load, liga o page_error da master page principal com o page_error da content page&lt;br&gt;&lt;br&gt;A content page se aproveita de toda a sequencia&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1014</link><title>ASP.NET : Referência a WebControls no Código JavaScript</title><description>&lt;br&gt;Frequentemente precisamos utilizar no javascript o nome dos nossos webControls, por&amp;#233;m nem sempre isso &amp;#233; uma tarefa f&amp;#225;cil : Quando nossos webControls encontram-se dentro de containers, tal como quando usamos master pages, login view ou outros casos semelhantes, o id do webControl se altera no client. &lt;br&gt;&lt;br&gt;Talvez voc&amp;#234;s j&amp;#225; tenham ouvido falar que os webControls possuem uma propriedade chamada clientid, que cont&amp;#233;m o nome que o controle ir&amp;#225; realmente ter quando estiver no client, mas como inserir este clientID no meio de um trecho de javascript como esse : &lt;br&gt;&lt;br&gt;&amp;lt;script language=&amp;quot;javascript&amp;quot;&amp;gt; &lt;br&gt;alert($get(&amp;quot;aqui entra o nome do objeto&amp;quot;).value); &lt;br&gt;&amp;lt;/script&amp;gt; &lt;br&gt;&lt;br&gt;A solu&amp;#231;&amp;#227;o inicial pode parecer simples, veja : &lt;br&gt;&lt;br&gt;&amp;lt;script language=&amp;quot;javascript&amp;quot;&amp;gt; &lt;br&gt;alert($get(&amp;quot;&amp;lt;%# obternome() %&amp;gt;&amp;quot;).value); &lt;br&gt;&amp;lt;/script&amp;gt; &lt;br&gt;&lt;br&gt;no code-behind criamos a fun&amp;#231;&amp;#227;o obternome : &lt;br&gt;&lt;br&gt;Protected Function obternome() As String &lt;br&gt;Return (Button1.ClientID) &lt;br&gt;End Function &lt;br&gt;&lt;br&gt;Mas ocorre um problema : Express&amp;#245;es utilizando o &amp;quot;#&amp;quot; apenas s&amp;#227;o processadas quando &amp;#233; solicitado um databind() no objeto dentro do qual elas encontram-se. Neste exemplo a express&amp;#227;o acima nunca seria processada. &lt;br&gt;&lt;br&gt;Mas poderiamos resolver da seguinte forma : &lt;br&gt;&lt;br&gt;&amp;lt;div id=&amp;quot;divteste&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt; &lt;br&gt;&amp;lt;script language=&amp;quot;javascript&amp;quot;&amp;gt; &lt;br&gt;alert($get(&amp;quot;&amp;lt;%# obternome() %&amp;gt;&amp;quot;).value); &lt;br&gt;&amp;lt;/script&amp;gt; &lt;br&gt;&amp;lt;/div&amp;gt; &lt;br&gt;&lt;br&gt;E no codeBehind : &lt;br&gt;&lt;br&gt;Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load &lt;br&gt;&lt;br&gt;divteste.DataBind() &lt;br&gt;&lt;br&gt;End Sub &lt;br&gt;&lt;br&gt;Desta forma for&amp;#231;amos o databind em uma &amp;quot;div&amp;quot; que na verdade n&amp;#227;o cont&amp;#233;m absolutamente nada al&amp;#233;m do javascript e geramos o nome client do nosso objeto naquela posi&amp;#231;&amp;#227;o. &lt;br&gt;&lt;br&gt;Uma d&amp;#250;vida comum : Por que n&amp;#227;o usar diretamente o page.databind() ? Simples : Porque al&amp;#233;m de ser muito mais pesado o page.databind() pode executar o vinculo de dados de algum objeto que n&amp;#227;o desejamos executar naquele momento, por isso o uso de page.databind n&amp;#227;o &amp;#233; aconselhavel. &lt;br&gt;&lt;br&gt;Outra observa&amp;#231;&amp;#227;o importante : como isso &amp;#233; para resolver problemas justamente causados por containers, esta dica http://www.bufaloinfo.com.br/dicas.asp?cod=810 sobre o findcontrol pode ser importante. &lt;br&gt;&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1009</link><title>ASP.NET : Tratando o page_error com master pages</title><description>&lt;br&gt;O evento Page_error &amp;#233; sem d&amp;#250;vida uma boa forma de tratar erros inesperados. Enquanto desejaremos dar um tratamento comum a todo erro inesperado, utilizar o application_error do global.asax &amp;#233; por demais custoso.&lt;br&gt;&lt;br&gt;No Visual Studio 2003 cri&amp;#225;vamos uma classe base e faziamos todas as p&amp;#225;ginas do site herdarem desta classe base. No Visual Studio 2005, por&amp;#233;m, surgiram as master pages. Parecia a solu&amp;#231;&amp;#227;o definitiva para algumas centraliza&amp;#231;&amp;#245;es - tal como o tratamento de erro centralizado.&lt;br&gt;&lt;br&gt;Mas infelizmente n&amp;#227;o foi bem assim. O page_error quando programado na master page simplesmente n&amp;#227;o &amp;#233; executado e o programador fica chupando dedo sem saber o que est&amp;#225; acontecendo.&lt;br&gt;&lt;br&gt;Qual o segredo ?&lt;br&gt;&lt;br&gt;Simples : O page_error trata o erro da p&amp;#225;gina em que ele est&amp;#225;, no caso a master page. Se algum erro ocorrer dentro da execu&amp;#231;&amp;#227;o da master page o page_error tratar&amp;#225; isso sem problema algum.&lt;br&gt;&lt;br&gt;Por&amp;#233;m se algum erro ocorrer na content page o page_Error da master page n&amp;#227;o &amp;#233; considerado - n&amp;#227;o est&amp;#227;o na mesma p&amp;#225;gina.&lt;br&gt;&lt;br&gt;A consequencia disso seria terr&amp;#237;vel, nos obrigaria a repetir o tratamento de erros em todas as p&amp;#225;gins. Ent&amp;#227;o, como resolver ?&lt;br&gt;&lt;br&gt;A solu&amp;#231;&amp;#227;o para isso &amp;#233; simples : No load da master page podemos vincular o tratador qe j&amp;#225; existe nas master page com o evento page_error da content page&lt;br&gt;&lt;br&gt;Veja como fica :&lt;br&gt;&lt;br&gt;    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load&lt;br&gt;        AddHandler Page.Error, AddressOf Page_Error&lt;br&gt;    End Sub&lt;br&gt;&lt;br&gt;Com isso o tratamento de erro ser&amp;#225; o mesmo para todas as p&amp;#225;ginas e n&amp;#227;o teremos o peso t&amp;#237;pico que o application error do global.asax nos causaria.&lt;br&gt;&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1008</link><title>ASP.NET : Utilizando multiplos mapas de site na aplicação</title><description>&lt;br&gt;Comentamos sobre t&amp;#233;cnicas para manipular o mapa de site nas dicas em ... e ... mas eventualmente mesmo estas duas t&amp;#233;cnicas podem n&amp;#227;o ser suficientes. &lt;br&gt;&lt;br&gt;Quando precisarmos realmente criar &amp;#225;reas de navega&amp;#231;&amp;#227;o separadas em nosso site podemos manipular os providers de sitemap. Isso mesmo : Os mapas de site tamb&amp;#233;m s&amp;#227;o baseados em providers.&lt;br&gt;&lt;br&gt;Normalmente quando adicionamos um arquivo de mapa de site este j&amp;#225; &amp;#233; adicionado com o nome default de web.sitemap. Por&amp;#233;m isso n&amp;#227;o &amp;#233; obrigat&amp;#243;rio, podemos adicionar arquivos de mapas de site adicionais, definindo nomes personalizados para cada arquivo de mapa de site.&lt;br&gt;&lt;br&gt;Ent&amp;#227;o vem a quest&amp;#227;o principal : Como fazer com que o sitemapDataSource reconhe&amp;#231;a os diferentes arquivos de mapa de site que adicionarmos ?&lt;br&gt;&lt;br&gt;Para isso devemos incluir no nosso web.config configura&amp;#231;&amp;#245;es do provider de sitemap para cada arquivo de mapa de site inserido.&lt;br&gt;&lt;br&gt;Veja como fica :&lt;br&gt;&lt;br&gt;&lt;br&gt;        &amp;lt;siteMap&amp;gt;&lt;br&gt;            &amp;lt;providers&amp;gt;&lt;br&gt;                &amp;lt;add siteMapFile=&amp;quot;web.sitemap&amp;quot; name=&amp;quot;MeuProvider1&amp;quot; type=&amp;quot;System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&amp;quot;/&amp;gt;&lt;br&gt;&lt;br&gt;                &amp;lt;add siteMapFile=&amp;quot;Mapa2.sitemap&amp;quot; name=&amp;quot;MeuProvider2&amp;quot; type=&amp;quot;System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&amp;quot;/&amp;gt;&lt;br&gt;            &amp;lt;/providers&amp;gt;&lt;br&gt;        &amp;lt;/siteMap&amp;gt;&lt;br&gt;&lt;br&gt;Criamos 2 providers de mapa de site no web.config, cada provider com um nome diferenciado. &lt;br&gt;&lt;br&gt;Ao utilizar o siteMapDataSource podemos inserir 2 siteMapDataSources na nossa aplica&amp;#231;&amp;#227;o e configurar a propriedade siteMapProvider com o nome do provider que desejamos que seja utilizado.&lt;br&gt;&lt;br&gt;Desta forma, podemos ter 2 mapas de site diferenciados em uma mesma aplica&amp;#231;&amp;#227;o.&lt;br&gt;&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1005</link><title>ASP.NET : Identificando o usuário em nosso site</title><description>&lt;br&gt;&lt;br&gt;Frequentemente precisamos identificar em nosso site quem &amp;#233; o usu&amp;#225;rio. &lt;br&gt;&lt;br&gt;O usu&amp;#225;rio, por&amp;#233;m, pode estar logado ou n&amp;#227;o estar logado. Quando o usu&amp;#225;rio n&amp;#227;o est&amp;#225; logado, o ASP.NET tem a capacidade de gerar um ID an&amp;#244;nimo para ele, j&amp;#225; quando o usu&amp;#225;rio est&amp;#225; logado, normalmente queremos recuperar o login do usu&amp;#225;rio.&lt;br&gt;&lt;br&gt;Ent&amp;#227;o, em toda parte do site em que precisarmos recuperar o ID do usu&amp;#225;rio, precisar&amp;#237;amos fazer um IF para verificar se o usu&amp;#225;rio est&amp;#225; logado ou n&amp;#227;o e recuperar o id an&amp;#244;nimo ou o login do usu&amp;#225;rio. Como podem observar, n&amp;#227;o &amp;#233; nada recomend&amp;#225;vel ter essa repeti&amp;#231;&amp;#227;o de l&amp;#243;gica espalhada por todo o site.&lt;br&gt;&lt;br&gt;Para resolver este problema podemos criar uma classe na pasta app_code e utiliza-la para centralizar as requisi&amp;#231;&amp;#245;es do id do usu&amp;#225;rio. Veja como fica :&lt;br&gt;&lt;br&gt;Public Class Usuario&lt;br&gt;    Public Shared ReadOnly Property idUsuario() As String&lt;br&gt;        Get&lt;br&gt;            If Current.User.Identity.IsAuthenticated Then&lt;br&gt;                Return (Current.User.Identity.Name)&lt;br&gt;            Else&lt;br&gt;                Return Current.Request.AnonymousID&lt;br&gt;            End If&lt;br&gt;        End Get&lt;br&gt;    End Property&lt;br&gt;End Class&lt;br&gt;&lt;br&gt;&lt;br&gt;Observe que a propriedade &amp;#233; definida como shared, para que n&amp;#227;o seja necess&amp;#225;rio criar uma inst&amp;#226;ncia da classe e definida como ReadOnly porque apenas faremos a leitura da informa&amp;#231;&amp;#227;o, n&amp;#227;o escrita.&lt;br&gt;&lt;br&gt;Assim sendo, de qualquer ponto do site podemos utilizar :&lt;br&gt;&lt;br&gt;Usuario.IdUsuario &lt;br&gt;&lt;br&gt;para recuperar o id do usu&amp;#225;rio, sem nos preocuparmos se ele encontra-se logado ou n&amp;#227;o.&lt;br&gt;&lt;br&gt;Lembre-se que no caso do id an&amp;#244;nimo, este precisa ser habilitado no web.config :&lt;br&gt;&lt;br&gt;&amp;lt;anonymousidentification enabled=&amp;quot;true&amp;quot; /&amp;gt;&lt;br&gt;&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1004</link><title>ASP.NET : Escondendo elementos do sitemap em uma treeview</title><description>&lt;br&gt;Uma treeview &amp;#233; um objeto normalmente utilizado para navega&amp;#231;&amp;#245;es laterais. Como tal, n&amp;#227;o &amp;#233; o objeto principal de navega&amp;#231;&amp;#227;o no site, a navega&amp;#231;&amp;#227;o principal do site &amp;#233; feita por um menu superior, por exemplo, a treeview fica sendo secund&amp;#225;ria.&lt;br&gt;&lt;br&gt;Assim sendo, como j&amp;#225; temos um menu no topo, certamente n&amp;#227;o desejaremos exibir toda a &amp;#225;rvore de navega&amp;#231;&amp;#227;o na treeview, mas apenas alguns elementos, os mais importantes certamente. Ent&amp;#227;o como fazer com que a treeview n&amp;#227;o exiba o sitemap inteiro, apenas parte dele ?&lt;br&gt;&lt;br&gt;Al&amp;#233;m da possibilidade de n&amp;#227;o exibir um n&amp;#243; do sitemap, existe a possibilidade de exibir um n&amp;#243; de forma n&amp;#227;o expandida e retirar da treeview os bot&amp;#245;es de expans&amp;#227;o, dando a treeview a apar&amp;#234;ncia de uma simples barra lateral.&lt;br&gt;&lt;br&gt;E por que n&amp;#227;o fazer uma simples barra lateral ? Porque com o sitemap temos mais versatilidade na manuten&amp;#231;&amp;#227;o da navega&amp;#231;&amp;#227;o do site.&lt;br&gt;&lt;br&gt;Mais uma vez, vamos utilizar o truque que demonstramos com o sitemap (em http://www.bufaloinfo.com.br/dicas.asp?cod=999 e http://www.bufaloinfo.com.br/dicas.asp?cod=811 ), criando atributos adicionais para o sitemap. Veja como fica um n&amp;#243; do sitemap com esse atributo :&lt;br&gt;&lt;br&gt;&amp;lt;siteMapNode title=&amp;quot;A Empresa&amp;quot; description=&amp;quot;Informa&amp;#231;&amp;#245;es sobre a empresa&amp;quot; url=&amp;quot;/a_empresa.asp&amp;quot; ImageURL=&amp;quot;/Images/empresa.gif&amp;quot; exibeArvore=&amp;quot;false&amp;quot;/&amp;gt;&lt;br&gt;&lt;br&gt;&amp;lt;siteMapNode title=&amp;quot;Treinamentos&amp;quot; description=&amp;quot;Informa&amp;#231;&amp;#245;es sobre treinamentos&amp;quot; url=&amp;quot;/treinamentos.asp&amp;quot; ImageURL=&amp;quot;/Images/treinamento.gif&amp;quot; expandido=&amp;quot;false&amp;quot;&amp;gt;&lt;br&gt;&lt;br&gt;Enquanto que &amp;quot;A empresa&amp;quot; encontra-se com o atributo &amp;quot;exibeArvore&amp;quot; false, para n&amp;#227;o aparecer no treeview, &amp;quot;Treinamentos&amp;quot; encontra-se com o atributo &amp;quot;expandido&amp;quot; false, para aparecer mas de forma reduzida, sem mostrar toda a &amp;#225;rvore abaixo deste n&amp;#243;.&lt;br&gt;&lt;br&gt;&lt;br&gt;Programamos ent&amp;#227;o o treenode databound para fazer com que, com base neste atributo, o n&amp;#243; n&amp;#227;o seja exibido. Isso sai um pouco do trivial porque o treenode n&amp;#227;o tem propriedade visible acess&amp;#237;vel neste ponto, ent&amp;#227;o temos realmente que eliminar o treenode da cole&amp;#231;&amp;#227;o de n&amp;#243;s :&lt;br&gt;&lt;br&gt;    Protected Sub SampleTreeView_TreeNodeDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) Handles SampleTreeView.TreeNodeDataBound&lt;br&gt;&lt;br&gt;        If Not IsNothing(e.Node.DataItem(&amp;quot;exibeArvore&amp;quot;)) AndAlso e.Node.DataItem(&amp;quot;exibeArvore&amp;quot;) = &amp;quot;false&amp;quot; Then&lt;br&gt;            SampleTreeView.Nodes.Remove(e.Node)&lt;br&gt;        End If&lt;br&gt;&lt;br&gt;        If Not IsNothing(e.Node.DataItem(&amp;quot;expandido&amp;quot;)) AndAlso e.Node.DataItem(&amp;quot;expandido&amp;quot;) = &amp;quot;false&amp;quot; Then&lt;br&gt;            e.Node.Collapse()&lt;br&gt;        End If&lt;br&gt;    End Sub&lt;br&gt;&lt;br&gt;Dois if's bem semelhantes para testar os atributos. Por&amp;#233;m no caso do exibeArvore removemos o n&amp;#243; da cole&amp;#231;&amp;#227;o Nodes. No caso do expandido aplicamos um Collapse.&lt;br&gt;&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1003</link><title>ASP.NET : Criando o Efeito de Hover para o Menu</title><description>&lt;br&gt;Sem d&amp;#250;vida que o controle de menu do ASP.NET &amp;#233; extremamente vers&amp;#225;til, com in&amp;#250;meros recursos gerando funcionalidades e permitindo um layout personalizado. &lt;br&gt;&lt;br&gt;Um dos recursos mais procurados por quem cria um menu &amp;#233; a gera&amp;#231;&amp;#227;o de um hover : Fazer o menu mudar de apar&amp;#234;ncia conforme o mouse passe sobre o menu. &lt;br&gt;&lt;br&gt;Na era do CSS, existe uma forma f&amp;#225;cil de fazer isso com CSS, vejam : &lt;br&gt;&lt;br&gt;.toggleopacity img{ &lt;br&gt;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=100,style=0); &lt;br&gt;-moz-opacity: 1; &lt;br&gt;border: 1px solid #ccc; &lt;br&gt;} &lt;br&gt;&lt;br&gt;.toggleopacity:hover img{ &lt;br&gt;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=100,FinishOpacity=40,style=3); &lt;br&gt;-moz-opacity: 0.7; &lt;br&gt;border: 1px solid navy; &lt;br&gt;} &lt;br&gt;&lt;br&gt;&lt;br&gt;Neste exemplo estamos aplicando um filtro Alpha sobre o menu, criando uma varia&amp;#231;&amp;#227;o na opacity no momento em que o mouse passa sobre o menu. Style 3 significa um formato em radial, a presen&amp;#231;a do finishOpacity significa que ser&amp;#225; um degrad&amp;#234; usando o Opacity. &lt;br&gt;&lt;br&gt;Feito isso, basta aplicar a classe toggleopacity no menu. &lt;br&gt;&lt;br&gt;Antes que perguntem : Sim, este efeito funciona no FireFox &lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=1001</link><title>ASP.NET : Simplificando a Personalização de Componentes com o TagMapping</title><description>&lt;br&gt;Na dica em http://www.bufaloinfo.com.br/dicas.asp?cod=999 mostramos como adicionar algumas funcionalidades a um webcontrol de menu, inclusive criando uma heran&amp;#231;a da classe menu para isso.&lt;br&gt;&lt;br&gt;Utilizar componentes personalizados exige uma maior organiza&amp;#231;&amp;#227;o no trabalho em grupo. Se o projeto for aberto em outra m&amp;#225;quina, o componente precisa estar presente l&amp;#225; tamb&amp;#233;m.&lt;br&gt;&lt;br&gt;Para minimizar este tipo de impacto o ASP.NET fornece um recurso conhecido como tag Mapping : Podemos, utilizando o web.config, mapear uma determinada tag existente na aplica&amp;#231;&amp;#227;o para um outro componente, de forma que a substitui&amp;#231;&amp;#227;o aconte&amp;#231;a em run-time.&lt;br&gt;&lt;br&gt;Desta forma, o projeto pode ser aberto mesmo em m&amp;#225;quinas que n&amp;#227;o tenham o componente presente, sendo o impacto da falta do componente minimizado.&lt;br&gt;&lt;br&gt;Veja como fazer no exemplo do menu :&lt;br&gt;&lt;br&gt;          &amp;lt;tagMapping&amp;gt;&lt;br&gt;            &amp;lt;add tagType=&amp;quot;System.Web.UI.WebControls.Menu&amp;quot; mappedTagType =&amp;quot;libControls.MenuImagens&amp;quot; /&amp;gt;&lt;br&gt;          &amp;lt;/tagMapping&amp;gt;&lt;br&gt;&lt;br&gt;Neste exemplo estamos mapeando a tag de menu para o nosso tipo de menu personalizado.&lt;br&gt;&lt;br&gt;Pontos Positivos&lt;br&gt;&lt;br&gt;Facilidade no trabalho em conjunto e manipula&amp;#231;&amp;#227;o do projeto em outras m&amp;#225;quinas sem a necessidade do componente&lt;br&gt;&lt;br&gt;Pontos Negativos&lt;br&gt;&lt;br&gt;Afeta todo o projeto&lt;br&gt;&lt;br&gt;S&amp;#243; funciona para componentes com recursos que n&amp;#227;o exijam manipula&amp;#231;&amp;#227;o em design-time. Voc&amp;#234; n&amp;#227;o conseguir&amp;#225; acessar propriedades da sua classe personalizada usando tag Mapping.&lt;br&gt;&lt;br&gt;</description></item><item><link>http://www.bufaloinfo.com.br/dicas.asp?cod=999</link><title>ASP.NET : Utilizando menus com Imagens e Mapa de Site</title><description>&lt;br&gt;&lt;br&gt;Na dica em http://www.bufaloinfo.com.br/dicas.asp?cod=811 mostramos como usar imagens com o mapa de site, fazendo um exemplo com uma treeview. Por&amp;#233;m isso n&amp;#227;o est&amp;#225; limitado a treeview, pode ser feito tamb&amp;#233;m com menus, permitindo criar menus baseados em imagem&lt;br&gt;&lt;br&gt;No mapa de site, adicionamos nos itens que desejamos um atributo novo, ImageURL - o mapa de site &amp;#233; vers&amp;#225;til para aceitar novos atributos.&lt;br&gt;&lt;br&gt;&amp;lt;siteMapNode title=&amp;quot;Treinamentos&amp;quot; description=&amp;quot;Informa&amp;#231;&amp;#245;es sobre treinamentos&amp;quot; url=&amp;quot;treinamentos.asp&amp;quot; ImageURL=&amp;quot;/Images/treinamento.gif&amp;quot;&amp;gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;Para que a imagem seja exibida no menu, precisamos programar o evento MenuItemDataBound para atribuir as imagens ao menu, veja :&lt;br&gt;&lt;br&gt;    Protected Sub mnuBufalo_MenuItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.MenuEventArgs) Handles mnuBufalo.MenuItemDataBound&lt;br&gt;&lt;br&gt;        If Not IsNothing(e.Item.DataItem(&amp;quot;ImageURL&amp;quot;)) Then&lt;br&gt;            e.Item.ImageUrl = e.Item.DataItem(&amp;quot;ImageURL&amp;quot;)&lt;br&gt;            e.Item.Text = String.Empty&lt;br&gt;        End If&lt;br&gt;&lt;br&gt;    End Sub&lt;br&gt;&lt;br&gt;&lt;br&gt;Observe que o IF nos cria a op&amp;#231;&amp;#227;o de usarmos ou n&amp;#227;o imagem, inclusive usarmos imagem para alguns itens de menu e n&amp;#227;o usarmos imagem para outros itens de menu&lt;br&gt;&lt;br&gt;Uma forma de simplificar isso, evitando termos que sempre programar este recurso, &amp;#233; criando uma nova classe menu com este c&amp;#243;digo, veja como fica :&lt;br&gt;&lt;br&gt;Public Class MenuImagens&lt;br&gt;    Inherits System.Web.UI.WebControls.Menu&lt;br&gt;&lt;br&gt;    Protected Overrides Sub OnMenuItemDataBound(ByVal e As System.Web.UI.WebControls.MenuEventArgs)&lt;br&gt;&lt;br&gt;        If Not IsNothing(e.Item.DataItem(&amp;quot;ImageURL&amp;quot;)) Then&lt;br&gt;            e.Item.ImageUrl = e.Item.DataItem(&amp;quot;ImageURL&amp;quot;)&lt;br&gt;            e.Item.Text = String.Empty&lt;br&gt;        End If&lt;br&gt;        MyBase.OnMenuItemDataBound(e)&lt;br&gt;&lt;br&gt;    End Sub&lt;br&gt;&lt;br&gt;End Class&lt;br&gt;&lt;br&gt;</description></item></channel></rss>