Artigos
.NET
Navegando na treeview do ASP.Net com setas do teclado
Palavras-chaves
TreeView, ASP.Net, Teclado, Setas, Javascript
Introdução
A treeview serve para navegar entre nós em uma estrutura de árvore divididos entre pais e filhos, essa estrutura é muito usada quando não se sabe a dimensão dos nós. Essa navegação só é disponível com o mouse no componente nativo do ASP.Net a partir da versão 2.0. O artigo mostra uma forma de adaptar a navegação em uma treeview do ASP.Net utilizando as setas do teclado e a tecla enter para ativar ou expandir o item através dos eventos Javascript, o que exige um trabalho maior para adaptar aos diversos browsers existentes.
Exemplo
O exemplo será feito no Visual Studio Team System 2008 e a linguagem C#. O exemplo também se aplica ao Visual Studio 2005 e VB.Net. Vamos aos passos para criar o projeto:
Passo 1
Abra o Visual Studio 2008, clique no menu Novo / Projeto, seleciona o tipo de projeto WEB e o template ASP.NET Web Application e chame sua aplicação de TesteTreeView. como mostra na Figura 1.
Figura 1 – Criando o projeto web
Passo 2
Na página default, que é aberta quando o projeto web é criado, acrescente os atributos ID e RUNAT na tag div com os respectivos valores divTree e Server, o resultado deve ficar como mostra a Figura 2. No exemplo tam´´em mudei a título da página para TesteTreeview.
Figura 2 – Adicionando o componente treeView na página Default.aspx
Passo 3
Na aba lateral esquerda ToolBox dentro na subdivisão Navigator arraste o controle TreeView para sua página Default.aspx entre as tags DIV. Somente para efeitos visuais escolhi um visual para a treeview, para selecionar um visual vá ao modo Design, localizado na parte inferior esquerda do Visual Studio 2008, seleciona a treeview e escolha um AutoFormat. Eu escolhi o modelo Simple. Ao final o código HTML deve estar como a Figura 3.
Figura 3 – HTML da página default com a treeview com o Autoformat Simple
Passo 4
Vamos adicionar uma pasta e criar o arquivo JavaScript que controlará os eventos na treeview. Na Solution Explorer do Visual Studio 2008, clique com o botão inverso no projeto, no menu Add clique em New Folder, como mostra a Figura 4.
Figura 4 – Adicionando nova pasta
Dê o nome da pasta de js, clique com o botão inverso na pasta js no menu Add clique em New Item, como mostra a Figura 5.
Figura 5 – Adicionando um novo arquivo a pasta js
Escolha o template JScript File e o nome do arquivo como EventosTree.js
Figura 6 – Criando o arquivo EventosTree.js dentro da pasta js
Adicione o código do Quadro 1 no arquivo criado.
function ClicouSetas(evt,tvNome) { evt = getEvent(evt); var tecla = getKeyCode(evt); if (document.activeElement == null) return true; if (document.activeElement.tagName.toLowerCase() != 'a') //se não for o link return true; if (tecla != 37 && tecla != 38 && tecla != 39 && tecla != 40 && tecla != 13) //se as teclas não forem as SETAS e não for o ENTER sai do método return true;
//TreeView_ToggleNode if (tecla == 13)//enter acionaItem(document.activeElement); else if (tecla == 39)//direita { var proximoItem = document.activeElement; var div_atual = proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.id; proximoItem = document.getElementById(tvNome + 't' + (parseInt(proximoItem.id.replace(tvNome + 't', '')) + 1).toString()); if (proximoItem) { if (document.activeElement.href.indexOf('focus') != -1 || document.activeElement.href.indexOf('TreeView_ToggleNode') != -1)//se existe a função para expandir { if (proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'div' && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.style.display != 'none' && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.id != div_atual) { proximoItem.focus(); //document.getElementById('ultimoFoco').value = proximoItem.id; } else acionaItem(document.activeElement); } } } else if (tecla == 37)//esquerda { var proximoItem = document.activeElement; var div_atual = proximoItem; while (div_atual.tagName.toLowerCase()!='div') div_atual = div_atual.parentNode; //busca o div atual div_atual = div_atual.parentNode; while (div_atual.tagName.toLowerCase() != 'div') div_atual = div_atual.parentNode;//busca o div do pai if (proximoItem.href.indexOf('focus') != -1 || proximoItem.href.indexOf('TreeView_ToggleNode') != -1)//se o nó está expandido fechar { var dvp = proximoItem.href.split(',')[proximoItem.href.split(',').length - 1].replace('\'', '').replace('\'', '').replace('document.getElementById(', '').replace(')', '').replace(')', ''); var proximo_div = document.getElementById(dvp); //qual o div que ele aciona if (proximo_div && proximo_div.style.display != 'none') { acionaItem(document.activeElement); return false; } }
while (proximoItem != null) { proximoItem = document.getElementById(tvNome + 't' + (parseInt(proximoItem.id.replace(tvNome + 't', '')) - 1).toString()); if (proximoItem && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.style.display != 'none' && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.id == div_atual.id) { try { proximoItem.focus(); //document.getElementById('ultimoFoco').value = proximoItem.id; break; } catch (ex) { continue; } } } } else if (tecla == 40)//baixo { var proximoItem = document.activeElement; while (proximoItem != null) { proximoItem = document.getElementById(tvNome + 't' + (parseInt(proximoItem.id.replace(tvNome + 't', '')) + 1).toString()); if (proximoItem && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'div' && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.style.display != 'none') { try { proximoItem.focus(); //document.getElementById('ultimoFoco').value = proximoItem.id; break; } catch (ex) { continue; } } } } else if (tecla == 38)//cima { var proximoItem = document.activeElement; while (proximoItem != null) { proximoItem = document.getElementById(tvNome + 't' + (parseInt(proximoItem.id.replace(tvNome + 't', '')) - 1).toString()); if (proximoItem && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.tagName.toLowerCase() == 'div' && proximoItem.parentNode.parentNode.parentNode.parentNode.parentNode.style.display != 'none') { try { proximoItem.focus(); //document.getElementById('ultimoFoco').value = proximoItem.id; break; } catch (ex) { continue; } } } } return false; } function acionaItem(item) { item.setAttribute('onclick', item.href); if (typeof (item.onclick) == 'function') item.onclick(); else item.click(); item.setAttribute('onclick', ''); //document.getElementById('ultimoFoco').value = item.id; }
//Recupera o código da tecla que foi pressionado function getKeyCode(evt) { var code; if (typeof (evt.keyCode) == 'number') code = evt.keyCode; else if (typeof (evt.which) == 'number') code = evt.which; else if (typeof (evt.charCode) == 'number') code = evt.charCode; else return 0;
return code; } // recupera o evento do form function getEvent(evt) { if (!evt) evt = window.event; //IE return evt; } |
Quadro 1 – Código do arquivo EventosTree.js
Passo 5
Vamos adicionar a referência do arquivo javascript na página default.aspx. Para isso vá a página e acrescente a linha de códgio do Quadro 2 entre as tags HEAD e o resultado deve ficar como na Figura 7.
<script src="js/EventosTree.js" type="text/javascript"></script> |
Quadro 2 – Referencia do arquivo javascript na página Default.apsx
Figura 7 – Referência do arquivo EventosTree.js na página Defulta.aspx
Passo 6
Agora vamos adicionar um código somente para preencher a treeview e setar o foco no primeiro elemento, você pode usar qualquer outro código ou banco de dados para preencher a sua treeview.
Na página Default.aspx, vá ao código da página apertando a tecla F7 e adicione o seguinte método do Quadro 3. Esse evento deve estar dentor da classe e fora do método Page_Load
private void CarregarTV() { TreeView1.Nodes.Clear(); TreeNode tr = new TreeNode(); for (int i = 0; i < 3; i++) { tr = new TreeNode("Pai_" + i.ToString(), i.ToString()); tr.SelectAction = TreeNodeSelectAction.Expand; for (int j = 0; j < 3; j++) tr.ChildNodes.Add(new TreeNode("Filho_" + i.ToString() + "_" + j.ToString(), i.ToString() + "_" + j.ToString())); TreeView1.Nodes.Add(tr); } //Focus no primeiro elemento ClientScript.RegisterStartupScript(this.GetType(), "focoTreeView", "if(document.getElementById('" + TreeView1.ClientID + "t0'))document.getElementById('" + TreeView1.ClientID + "t0').focus();", true); } |
Quadro 3 – Método em C# para preencher a treeview e setar o foco no primeiro elemento
Destaquei a linha do Quadro 3 que é um ponto interessante, nesse exemplo quando clicar com o mouse sobre um nó pai ele será expandido. A ultima linha do código seta o foco no primeiro elemento da treeview.
Passo 7
O último passo é ligar o div ao evento do js e chamar o método para carregar a treeview ao abrir a página. Para isso altere o evento Page_Load no código da página default como mostra o Quadro 4.
protected void Page_Load(object sender, EventArgs e) { divTree.Attributes.Remove("onkeydown"); divTree.Attributes.Add("onkeydown", "return ClicouSetas(event,'" + TreeView1.ClientID + "');"); if (!IsPostBack) CarregarTV(); } |
Quadro 4 – Código do evento Page_Load da página default.aspx
Conclusão
O exemplo mostra uma forma de melhorar a forma de acesso às informações da página, melhorando a usabilidade para seus usuários. Isso é somente um passo, que faz grande diferença para seu produto. O resultado final é mostrado na Figura 8, ao abrir a página o foco inicial fica no primeiro elemento da treeview e as setas para baixo, cima, esquerda e direita já funcionam e a tecla enter aciona o item ou expande.
Figura 8 – Resultado final com a treeview navegada pelo teclado
Quem tiver alguma dúvida pode me mandar no e-mail tiago@grupodias.com.br
Fonte do exemplo no endereço http://cid-f8d073fe4fb32051.skydrive.live.com/self.aspx/P%c3%bablico/artigos/TesteTreeView.zip
Um grande abraço,
Tiago Silva Dantas Franco
Especialista em gestão da tecnologia da informação