161 messaggi dal 07 settembre 2009
Salve a tutti =)
ho necessità di creare un menù facilmente riutilizzabile per tutti i miei siti, così da non dover riscrivere tutte le volte la stessa cosa, ed ho pensato ai ListView.
Il punto è che i menù sono a 2 livelli, Categoria e Voce di menù, e mi chiedevo quale template fosse più adatto, se due ListView nidificati, dove il primo stampa le categorie ed il secondo stampa le voci di menù per ogni singola categoria, o se fare un solo ListView con Categoria ed una Label che stampa tutte le voci di menù, o ancora se fare un template con categoria e voce di menù, dove stampo tutte le voci di menù normalmente e le categorie le stampo solo una volta ad ogni cambio di IDCategoria (il che richiede un if ad ogni riga per verificare se devo stampare o meno la categoria).

Ognuno ha dei pro e dei contro, i ListView nidificati mi permettono di modificare facilmente il template senza toccare (quasi mai) il sorgente ma sono comunque 2 ListView nidificati e le performance potrebbero risentirne se si dovessero avere tante categorie, le voci di menù all'interno della Label è una soluzione più performante (almeno credo) ma mi costringe a inserire il codice html nel sorgente il che rende le modifiche un pò più lunghe, la terza soluzione ha quel controllo che faccio tutte le volte, in più non vorrei che il fatto di avere delle righe "fantasma" sporcasse il codice html anche se quest'ultima cosa magari è più una pippa mentale che altro.

E nel caso avessi 3 o più livelli di menù come consigliate di procedere? i ListView nidificati con l'aumentare dei livelli la vedo una soluzione poco opportuna in termini di performance.

Voi quale soluzione adottereste? Se avete soluzioni di diverso tipo anche senza utilizzare ListView va comunque bene, mi serve giusto per farmi un'idea su come ottimizzare al meglio i miei lavori.

Come sempre grazie per il vostro supporto.


Davide
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao,
i ListView annidati non sono la migliore soluzione per i dati di tipo gerarchico perché, come hai sottolineato, non scalano bene all'aumentare dei livelli.

Asp.Net ti mette a disposizione il controllo asp:Menu che è proprio pensato per questo tipo di situazioni ma immagino che tu l'abbia scartato perché non ti dà un controllo completo sul markup prodotto.

Quindi si potrebbe realizzare un controllo simile all'asp:Menu, che supporti un numero qualsiasi di livelli e che ti lasci personalizzazione l'output. Per iniziare a farlo, creati una classe che eredita da HierarchicalDataBoundControl (la stessa da cui anche il Menu eredita).

public class MyMenu : HierarchicalDataBoundControl, INamingContainer
{
  //implementazione
}

Implementare l'interfaccia INamingContainer invece è uno dei passi necessari a rendere MyMenu un templated control, cioè per dargli il supporto ai vari tag <???Template> in cui inserirai i vari pezzi di markup.

Non è la cosa più semplice che si possa realizzare ma con un po' di pazienza otterrai un ottimo risultato.

Qui ne hanno realizzato uno che produce delle liste <ul> annidate.
http://weblogs.asp.net/dannychen/archive/2005/12/19/433523.aspx

Mantieni il markup il più semplice possibile, come vedi in quell'articolo, così che tu possa riutilizzare il controllo in vari siti. Potrai dargli aspetti diversi grazie al CSS.
Delle <ul> annidate sono sufficienti per realizzare anche un menu a comparsa senza ricorrere al javascript.
http://www.jankoatwarpspeed.com/post/2009/01/19/Create-Vimeo-like-top-navigation.aspx

Poi, come DataSource di questo controllo puoi usare un SiteMapDataSource, che è in grado di leggere i dati di navigazione dal file web.sitemap di asp.net o da qualsiasi altra fonte (es. il database).
http://www.aspitalia.com/articoli/asp.net2/DataSource-p-2.aspx#title_4

ciao
Modificato da BrightSoul il 12 ottobre 2012 22.27 -

Enjoy learning and just keep making
161 messaggi dal 07 settembre 2009
Grazie per la risposta.
La tua soluzione è molto interessante, ma non ho particolare familiarità con l'ereditarietà di una classe, ne tanto meno con HierarchicalDataBoundControl. Avresti qualche link su cui potermi meglio informare su questi 2 argomenti?
Apprendere cose nuove è sempre utile, soprattutto in questo lavoro =)

Grazie.


Davide
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao, certo, su msdn si trovano buoni articoli.
Questi sono sull'ereditarietà, che ti consente di derivare da una classe per estenderne il comportamento, eventualmente alterandolo o aggiungendo nuove funzionalità. E' uno dei cosiddetti pilastri della programmazione orientata agli oggetti.
http://msdn.microsoft.com/it-it/library/ms173149.aspx
http://support.microsoft.com/kb/307205/it

Ereditare da HierarchicalDataBoundControl ti permette di creare un controllo web che ha già in sé la logica per collegarsi ad una fonte di dati gerarchica. Sta a te, estendendo quella classe, aggiungere la logica per presentare quei dati in HTML.
Qui trovi un altro articolo, in aggiunta a quello che avevo messo nel post precedente, che porta un esempio di codice su come realizzare il controllo.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.hierarchicaldataboundcontrol.aspx

Esamina quel codice, poi inglobalo nel tuo progetto e, piano piano, personalizzalo secondo le tue esigenze.
Per me l'altro articolo è più vicino a ciò che devi fare tu, dato che produce delle liste <ul> annidate. Ecco il codice completo del controllo:
http://weblogs.asp.net/dannychen/articles/433525.aspx

Quando l'avrai preparato, legalo ad una sorgente di dati. Ovviamente questa sorgente non sarà una lista di elementi, ma una gerarchia di elementi. I controlli di asp.net in grado di produrre una sorgente dati di quel tipo sono l'XmlDataSource e il SiteMapDataSource, quest'ultimo collegabile ad un provider personalizzato.

Se nessuno dei due dovesse incontrare le tue esigente puoi, ancora una volta, ereditare dalla classe HierarchicalDataSourceControl (o implementare l'interfaccia IHierarchicalDataSource) e determinare tu con quale logica generare la gerarchia dei dati.

Vedrai che verrà fuori un bel lavoro.

Enjoy learning and just keep making
161 messaggi dal 07 settembre 2009
Grazie =)
in effetti ho "studiato" l'ereditarietà delle classi, ma è un argomento che risale a qualche anno fa (ai tempi della scuola) e del codice da utilizzare non ricordo più granchè =P

Il menù avevo intenzione di farlo tramite div invece che con ul, spesso mi trovo a che fare con grafiche particolari e con i div mi ci ritrovo meglio... o dici che gli ul siano lo stesso più indicati?

Per quanto riguarda il sorgente mi studierò bene il SiteMapDataSource.

Ancora grazie


Davide
161 messaggi dal 07 settembre 2009
Premettendo che non ho ancora creato il nuovo template, benchè i link risultino abbastanza chiari e che quindi non credo che incontrerò grosse difficoltà su questo, ho alcuni problemi con il binding.

Ho capito che bisogna usare un binding di tipo HierarchicalDataSourceControl e per quale motivo, ma non trovo esempi chiari su come crearne uno che prenda i dati dal database.
Sul msdn ho visto questo
http://msdn.microsoft.com/library/system.web.ui.hierarchicaldatasourcecontrol.aspx ma non è ne chiaro ne sembra contenga quello che cerco...

Poi mi chiedo il modo in cui l'sql deve riprodurre i risultati... attualmente l'sql che utilizzo stampa i dati "in ordine gerarchico", quindi prima la categoria, poi le relative sottocategorie, le sottosottocategorie di ogni sottocategoria e via dicendo per il numero di livelli (che può essere infinito, infatti l'sql è scritto dinamicamente e mi ha fatto perdere kg e kg di neuroni)...

Mi servirebbero alcuni esempi chiari, magari un paio di link anche con database semplici.

Come sempre grazie per l'aiuto.


Davide
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao,
gli HierarchicalDataBoundControl come il Menu e la TreeView vogliono come DataSource un oggetto che implementi o l'interfaccia IHierarchicalEnumerable o la IHierarchicalDataSource.
L'esempio che hai trovato su MSDN mostra per l'appunto come realizzare un controllo in grado di funzionare come sorgente dati perché implementa la IHierarchicalDataSource, come si vede da questa riga di codice.

public class FileSystemDataSource : HierarchicalDataSourceControl, IHierarchicalDataSource


doppiomango ha scritto:

non è ne chiaro ne sembra contenga quello che cerco...

Capisco il motivo della confusione, effettivamente lì non mostrano solo il codice essenziale ma lo hanno arricchito con tutto ciò che serve per leggere dati dal file system. E questo è un altro punto che rende l'esempio non perfettamente idoneo al tuo caso: tu vuoi leggere i dati dal db e non dal filesystem.

Comunque, se lo studi meglio e capisci cosa hanno voluto realizzare, è probabile che riuscirai ad adattarlo al tuo caso.

bisogna usare un binding di tipo HierarchicalDataSourceControl

Non necessariamente. Come ripeto, è sufficiente una classe (e non per forza un controllo) che implementi IHierarchicalEnumerable o IHierarchicalDataSource.

Spezza il problema in due parti:
  • Creazione di una classe che implementi una delle due interfacce richieste
  • "Proiettare" il risultato ottenuto dal database su quella classe. Dato che il tuo codice già stampa i dati in ordine gerarchico, allora completare questo punto sarà abbastanza facile. Non dovrai più "stampare" ma istanziare degli oggetti.


Per il primo punto, inizia scrivendoti una classe tipo questa:
public class Pagina
{
    public string Titolo { get; set; }
    public string Percorso { get; set; }
    List<Pagina> Sottopagine { get; set; }
}
Come vedi, questa classe Pagina è idonea a realizzare una struttura dati gerarchica perché al suo interno contiene una collezione di altri oggetti Pagina dipendenti da essa.

Prosegui facendole implementare IHierarchicalDataSource e da lì, piano piano e senza scoraggiarti, vai avanti. Scoprirari che "Sottopagine" non può essere una List<Pagina> pura e semplice, ma dovrà implementare anche IHierarchicalEnumerable. Ci arriverai implementando un metodo alla volta, magari aiutati con un reflector tipo JustDecompile per capire come altre classi del .NET framework hanno implementato quell'interfaccia.

Anche se dovessi impiegare alcune ore per ottenere un risultato, sarà stato tempo ben speso perché si tratta di un'ottima attività formativa.

doppiomango ha scritto:
Mi servirebbero alcuni esempi chiari, magari un paio di link anche con database semplici.

Intanto cimentati, poi domani se ho un po' di tempo libero ti mando degli esempi di codice. Qui pure ne trovi uno abbastanza chiaro.
http://www.codeproject.com/Articles/19639/Implementing-IHierarchy-Support-Into-Your-Custom-C

ciao
Modificato da BrightSoul il 06 novembre 2012 00.31 -

Enjoy learning and just keep making
161 messaggi dal 07 settembre 2009
Come sempre grazie per l'aiuto =)

Lo scoraggiamento non c'è fortunatamente, non è la prima volta che mi trovo a dover apprendere cose di questo calibro ma fortunatamente sono (quasi) sempre riuscito ad ottenere i risultati sperati, anche grazie all'aiuto di questo forum...

Attualmente ho ridato un'occhiata a un pò di cose e oltre ad aver (ri)appreso l'utilizzo di alcune nozioni mi accordo che la mia lacuna più grande risiede nella conoscenza delle funzionalità della classe da ereditare. Negli esempi che ho trovato a volte non capisco quale comando appartiene alla classe padre e quali sono le sue funzioni, e da dove vengono presi i dati.

Mentre la mia ricerca continua aspetterò anche i tuoi esempi, purchè, ovviamente, non sia di troppo disturbo.

Davide

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.