Le domeniche pomeriggio tra le fredde Alpi sono tristi. Il sole sorge tardi e tramonta presto. Fa freddo. Eccomi allora a fare le mie prove - utili o meno - con .net e altri divertimenti simili. In questi giorni mi trovo troppo spesso a far uso di treeview. Se per la versione 2.0 di asp.net il web control inserito può definirsi sufficiente per il 90% delle situazioni, per asp.net 1.1 la cosa non può definirsi così rosea. L'uso del treeview presente nei wbecontrol scaricabili in aggiunta dal sito di Microsoft è limitata a Explorer, e se non ricordo male, non permette il caricamento dinamico dei nodi "figli".
L'argomento lo avevo già trattato in un mio vecchio blog. E sempre in quel blog citavo un treeview che personalmente trovato, e trovo, ben fatto, quello realizzato con una manciata di righe di codice Javascript e CSS, presente sul portale Constile. L'unico suo difetto è l'impossibilità di caricare dinamicamente i nodi figli. Allora perché non ampliare questo treeview aggiungendo, grazie alla moda del momento - Ajax - questa funzionalità?
Non ho mai nascosto che l'implementazione per me meglio fatta, per semplicità di utilizzo e di installazione, è quella creata da Matteo Casati che si trova a questo link. Grazie alle sue funzioni Javascript è possibile richiamare dei web services per ottenere le informazioni desiderate per l'aggiornamento della pagina senza il caricamento completo della stessa. Mi fermo qui, di Ajax se n'è parlato fin troppo in questo periodo, un'ulteriore spiegazione di cosa sia è inutile.
Uniamo dunque le due cose per ottenere quanto voluto. Dal link a fondo blog è presente un link dove scaricare l'esempio scritto (esempio che è possibile scaricare solo dopo all'autenticazione a questo sito). L'esempio è composto da una sola pagina asp.net che visualizza in due zone della pagina, i due treeview: il primo è così come è spiegato sul sito Constile, il secondo è con l'aggiunta del caricamento dinamico dei nodi figlio:
A prima vista non c'è differenza, ma se clicchiamo su un altro nodo vedremo l'effetto voluto del caricamento dei dati con una chiamata al web services:
Voluto perché nella chiamata del web services è presente il comando per rallentare la risposta:
System.Threading.Thread.Sleep(300);
Per simulare una situazione reale ho creato un database Access contenente una tabella con tre campi:
- id
- voce
- padre
La voce "padre" è relazionata con "id", in questo modo posso inserire tutte le voci dei nodi all'interno di un'unica tabella in questo modo:
Ogni singolo record avrà come padre il record con "id" uguale a "padre". I record con valore zero, non hanno padri.
Creata la pagina html includendo lo script per richiamare i web services, ho scritto il mio codice per richiamare il tutto:
<script type="text/javascript"> <!-- // Eseguito immediatamente var url='<%=Url%>';
// Funzioni per l'albero function mmenu(mID) { var menu = document.getElementById(mID); var display = menu.style.display; menu.style.display = (display == "block") ? "none" : "block"; menu.parentNode.style.listStyleImage = (display == "block") ? "url(images/cartellachiusa.gif)" : "url(images/cartellaaperta.gif)"; }
window.onload = function() { // Precarica immagini if (document.images) { var immagine1=new Image; immagine1.src='images/cartellaaperta.gif'; var immagine2=new Image; immagine2.src='images/cartellachiusa.gif'; var immagine3=new Image; immagine3.src='images/doc.gif'; } var uls = document.getElementsByTagName("ul"); for (i=0;i<uls.length;i++) { if(uls[i].className=="submenu")uls[i].style.display = "none"; CreaTree('0'); } }
var attuale=''; function CreaTree(oggetto) { attuale=oggetto; var espandere=window.document.getElementById(attuale); if (espandere.innerHTML=='') { // Non c'è ancora nulla, carico... espandere.innerHTML="Caricamento..."; mmenu(attuale); var pl = new SOAPClientParameters(); pl.add("livello", oggetto); SOAPClient.invoke(url, "CreaAlbero", pl, true, CreaTree_Back); } else mmenu(attuale); } function CreaTree_Back(r) { var espandere=window.document.getElementById(attuale); if (espandere!=null) espandere.innerHTML=r; } function Risultato(v) { alert(v); } //--> </script>
L'unica funzione non modifica è "mmenu". Alcune modifiche alla funzione caricata all'onload di pagina per il precaricamento delle immagini e per la creazione della base della treeview dinamica: CreaTree('0'). Esso fa riferimento al tag <ul id='0'></ul> presente nel codice html della pagina. "CreaTree" richiama il web sercices "CreaAlbero", che non fa altro che richiedere i record aventi padre il codice passato:
[WebMethod] public string CreaAlbero(string livello) { System.Threading.Thread.Sleep(300); DataTable dt; if (livello.Length==1) dt=Figli(0); else dt=Figli(Convert.ToInt32(livello.Substring(livello.LastIndexOf("-")+1))); StringBuilder sb=new StringBuilder(); foreach (DataRow dr in dt.Rows) { // Controllo che abbia figli if (dr["numero_figli"].ToString()=="0") { // Non ha figli sb.Append("<li><a href='#' onclick='Risultato(\""); sb.Append(dr["id"]); sb.Append("\")'>"); sb.Append(dr["voce"]); sb.Append("</li>\r\n"); } else { // Ha figli sb.Append("<li class='menu'>\r\n"); sb.Append("<a href=\"javascript:CreaTree('"); sb.Append(livello); sb.Append("-"); sb.Append(dr["id"]); sb.Append("')\">"); sb.Append(dr["voce"]); sb.Append("</a>\r\n"); sb.Append("<ul class=\"submenu\" id='"); sb.Append(livello); sb.Append("-"); sb.Append(dr["id"]); sb.Append("' style=\"display = 'none';\"></ul>"); sb.Append("</li>\r\n"); } } return sb.ToString(); }
Questa funzione ritorna il codice HTML puro con i fili del nodo passato, diversificando la creazione nel caso questi abbiamo loro stessi dei figli.
Non proseguo oltre con le spiegazioni. Sono stanco, ed ho voglia di panettone. Il tutto è così semplice che è sufficiente una lettura per capire il funzionamento di tutto... L'esempio da provare e esaminare è possibile scaricarlo da questo link.
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- C# e Net 6 in Kubernetes con Prometheus e Grafana, il 12 gennaio 2022 alle 21:58
- Snaturare Kubernetes evitando i custom container Docker, il 6 gennaio 2022 alle 19:40
- Provando Kaniko in Kubernetes come alternativa a Docker per la creazione di immagini, il 18 dicembre 2021 alle 20:11
- Divertissement con l'OpenID e Access Token, il 6 dicembre 2021 alle 20:05
- Operator per Kubernetes in C# e Net Core 6., il 28 novembre 2021 alle 19:44
- RBAC in Kubernetes verso gli operator, il 21 novembre 2021 alle 20:52