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.
- Entity Framework e più tabelle in una entity
- L'Entity Framework e le custom class coinvolte nei where...
- Entity Framework e l'ereditarietà (Single Table Inheritance)
- L'entity Framework e i vincoli FOREIGN KEY
- Lazy Loading con l'Entity Framework
- A volte ritornano... GridView vs Repeater vs ListView vs Custom
tr00per ha scritto:
come facico a scaricare questo esempio? il link difianco non è attivo...
Alla fine del post c'è il link: L'esempio da provare e esaminare è possibile scaricarlo da questo link
HTH
Modificato da m.casati il 05 dicembre 2007 10.45 -
Ciao e buongiorno a tutti, ho trovato molto interessante il vostro sito, soprattutto l'argomento "Treeview con caricamento dinamico dei nodi 'figlio'",
questo problema mi ha dato molto da fare, ma grazie a voi ce l'ho fatta,
vi chiedo se qualcuno può darmi indicazioni su come realizzare la stessa cosa in Visual Basic 6, o comunque dove posso cercarla.
grazie mille anticipatamente.
Come prima cosa un enorme "grazie" ad Andrea per i complimenti che mi ha fatto
Troppo buono (in fondo nemmeno io credo che la mia libreria sia "la migliore" in senso assoluto... ha sicuramente alcuni limiti rispetto, ad esempio, ad Ajax.NET... Certo: anche qualche vantaggio c'è...
Quanto alle considerazioni sul controllo TreeView non posso che concordare: sarà che ho creato controlli ad albero ben prima che arrivasse il .NET framework e che ho una certa confidenza con JavaScript e CSS, ma non sono mai stato particolarmente affascinato dalla TreeView (in fondo - e l'esempio di Constile usato da AZ ne è l'ennesima conferma - bastano veramente poche righe per fare un alberello di nodi!).
Qualche settimana fa ho fatto praticamente la stessa cosa mostrata nel post (caricavo nel tree un file system anziché un set di record ma cambia poco). L'unica differenza implementativa rispetto ad Andrea: il mio webservice non restituiva l'html ma la gerarchia di nodi (id, label, childs). Svantaggi? Un po' più di lavoro lato client (javascript) per il rendering. Vantaggi: meno dati scambiati via AJAX e possibilità di usare il servizio in più pagine (con grafica diversa).
Concludo con: bravo Andrea! Ottimo lavoro, come sempre del resto!
A presto,
Matteo
m.casati <m.casati> ha scritto:
Come prima cosa un enorme "grazie" ad Andrea per i complimenti che mi ha fatto
Meritatissimi!
Troppo buono (in fondo nemmeno io credo che la mia libreria sia "la migliore" in senso assoluto... ha sicuramente alcuni limiti rispetto, ad esempio, ad Ajax.NET... Certo: anche qualche vantaggio c'è...)
Mi raccomando, continua a supportare quel tuo codice, ho quasi convinto un altro programmatore ad utilizzarlo
Qualche settimana fa ho fatto praticamente la stessa cosa mostrata nel post (caricavo nel tree un file system anziché un set di record ma cambia poco). L'unica differenza implementativa rispetto ad Andrea: il mio webservice non restituiva l'html ma la gerarchia di nodi (id, label, childs). Svantaggi? Un po' più di lavoro lato client (javascript) per il rendering. Vantaggi: meno dati scambiati via AJAX e possibilità di usare il servizio in più pagine (con grafica diversa).
Ti confesso (ma che rimanga tra noi!
Una curiosità, quel treeview che hai creato, è free? E' visionabile?
Concludo con: bravo Andrea! Ottimo lavoro, come sempre del resto!
Ti ringrazio!
A presto,
Matteo
Ciao!
andrewz ha scritto:
Mi raccomando, continua a supportare quel tuo codice, ho quasi convinto un altro programmatore ad utilizzarlo
Non dubitarne! Anzi: se hai trovato qualche bug o hai suggerimenti per migliorarlo... benvenuto!
Un po' mi è dispiaciuto constatare che i feedback e le correzioni mi siano arrivati tutti da stranieri (india, spagna, russia, francia, singapore, ecc.)
Gli italiani (che restano il bacino di utenza maggiore di GURU4.net) si fanno sentire ben poco...
Grazie a te per l'aiuto nella diffusione del verbo!
Una curiosità, quel treeview che hai creato, è free? E' visionabile?
A grande linee ho fatto quello che hai fatto tu, creando server side "l'impalacatura" dei nodi come struttura html, un po' di javascript per il toggle dei nodi e per la selezione di un nodo e un po' di css per il rendering grafico... insomma, niente di particolare!
Allo stato attuale non ho estratto il codice che crea la struttura del filesystem in un controllo... ma conto di farlo, creando un "FileManager" che gestisca un filesystem remoto via ASP.NET.
Appena riesco (= trovo il tempo!) ad impacchettare il FileManager in una dll e creare una demo, lo pubblico (free come sempre, s'intende!)
Credo sia più interessante che non il semplice tree, no?
m.casati <m.casati> ha scritto:
Non dubitarne! Anzi: se hai trovato qualche bug o hai suggerimenti per migliorarlo... benvenuto!
Un po' mi è dispiaciuto constatare che i feedback e le correzioni mi siano arrivati tutti da stranieri (india, spagna, russia, francia, singapore, ecc.)
Gli italiani (che restano il bacino di utenza maggiore di GURU4.net) si fanno sentire ben poco...
Forse perché, come nel mio caso, non ho trovato nessun problema nel suo funzionamento
Allo stato attuale non ho estratto il codice che crea la struttura del filesystem in un controllo... ma conto di farlo, creando un "FileManager" che gestisca un filesystem remoto via ASP.NET. Appena riesco (= trovo il tempo!) ad impacchettare il FileManager in una dll e creare una demo, lo pubblico (free come sempre, s'intende!) Credo sia più interessante che non il semplice tree, no?
Sì, eccome!
Nel mio caso ho preferito un caso reale di contenuto di una tabella, perché nel 99,9% chi ha bisogno di un treeview i dati li prende da una fonte dati.
Ciao e auguri!
Aggiungi un nuovo commento »»»
Per inserire un commento, devi registrarti alla nostra community.




Stampa
Download 
10annidi.ASPItalia.com: iscriviti alla competizione e vinci fantastici premi ogni mese!
come facico a scaricare questo esempio? il link difianco non è attivo...
Continua »»» | Rispondi »»»