Filtro master/dettaglio tra due pagine usando un controllo ripetitore e DataList (C#)
In questa esercitazione viene illustrato come separare un report master/dettaglio tra due pagine. Nella pagina "master" viene usato un controllo Repeater per eseguire il rendering di un elenco di categorie che, quando si fa clic, l'utente verrà visualizzato nella pagina "dettagli" in cui un datalist a due colonne mostra tali prodotti appartenenti alla categoria selezionata.
Introduzione
Nell'esercitazione precedente è stato illustrato come visualizzare i report master/dettagli in una singola pagina Web usando DropDownLists per visualizzare i record "master" e un Oggetto DataList per visualizzare i "dettagli". Un altro modello comune usato per i report master/dettagli consiste nell'avere i record master in una pagina Web e i dettagli su un altro. Nell'esercitazione precedente filtro master/dettaglio su due pagine , è stato esaminato questo modello usando GridView per visualizzare tutti i fornitori nel sistema. GridView include un oggetto HyperLinkField, che viene eseguito il rendering come collegamento a una seconda pagina, passando lungo l'oggetto SupplierID
nella querystring. La seconda pagina usa GridView per elencare i prodotti forniti dal fornitore selezionato.
Tali report master/dettaglio a due pagine possono essere eseguiti anche usando i controlli DataList e Repeater. L'unica differenza è che né DataList né Repeater forniscono il supporto per il controllo HyperLinkField. È invece necessario aggiungere un controllo Web HyperLink o un elemento HTML di ancoraggio (<a>
) all'interno del ItemTemplate
controllo . La proprietà HyperLink NavigateUrl
o l'attributo dell'ancoraggio href
possono quindi essere personalizzati usando approcci dichiarativi o programmatici.
In questa esercitazione verrà illustrato un esempio che elenca le categorie in un elenco puntato in una sola pagina usando un controllo Ripetitore. Ogni elemento di elenco includerà il nome e la descrizione della categoria, con il nome della categoria visualizzato come collegamento a una seconda pagina. Facendo clic su questo collegamento, l'utente verrà eseguito il whisking nella seconda pagina, in cui un Oggetto DataList mostrerà i prodotti che appartengono alla categoria selezionata.
Passaggio 1: Visualizzazione delle categorie in un elenco puntato
Il primo passaggio della creazione di un report master/dettaglio consiste nel visualizzare i record "master". Pertanto, la prima attività consiste nel visualizzare le categorie nella pagina "master". Aprire la CategoryListMaster.aspx
pagina nella DataListRepeaterFiltering
cartella, aggiungere un controllo Repeater e, dallo smart tag, scegliere di aggiungere un nuovo OggettoDataSource. Configurare il nuovo OggettoDataSource in modo che acceda ai dati dal CategoriesBLL
metodo della GetCategories
classe (vedere la figura 1).
Figura 1: Configurare ObjectDataSource per usare il metodo della GetCategories
classe (fare clic per visualizzare l'immagineCategoriesBLL
full-size)
Definire quindi i modelli di Repeater in modo che visualizzino ogni nome di categoria e descrizione come elemento in un elenco puntato. Non è ancora necessario avere ogni collegamento di categoria alla pagina dei dettagli. Di seguito viene illustrato il markup dichiarativo per Repeater e ObjectDataSource:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"
EnableViewState="False">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><%# Eval("CategoryName") %> - <%# Eval("Description") %></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
Con questo markup completato, è necessario un momento per visualizzare lo stato di avanzamento tramite un browser. Come illustrato nella figura 2, il ripetitore esegue il rendering come elenco puntato che mostra il nome e la descrizione di ogni categoria.
Figura 2: Ogni categoria viene visualizzata come elemento elenco puntato (fare clic per visualizzare l'immagine a dimensioni complete)
Passaggio 2: Trasformare il nome della categoria in un collegamento alla pagina Dettagli
Per consentire a un utente di visualizzare le informazioni "dettagli" per una determinata categoria, è necessario aggiungere un collegamento a ogni elemento elenco puntato che, quando viene fatto clic, porterà l'utente alla seconda pagina (ProductsForCategoryDetails.aspx
). Questa seconda pagina visualizzerà quindi i prodotti per la categoria selezionata usando un oggetto DataList. Per determinare la categoria il cui collegamento è stato fatto clic, è necessario passare la categoria CategoryID
selezionata alla seconda pagina tramite un meccanismo. Il modo più semplice e semplice per trasferire i dati scalari da una pagina a un altro consiste nell'esecuzione della querystring, ovvero l'opzione che verrà usata in questa esercitazione. In particolare, la ProductsForCategoryDetails.aspx
pagina prevede che il valore selezionato categoryID
venga passato tramite un campo querystring denominato CategoryID
. Ad esempio, per visualizzare i prodotti per la categoria Bevande, con un CategoryID
valore pari a 1, un utente visiterebbe ProductsForCategoryDetails.aspx?CategoryID=1
.
Per creare un collegamento ipertestuale per ogni elemento elenco puntato nel ripetitore, è necessario aggiungere un controllo Web HyperLink o un elemento di ancoraggio HTML (<a>
) all'oggetto ItemTemplate
. Negli scenari in cui viene visualizzato lo stesso collegamento ipertestuale per ogni riga, entrambi gli approcci saranno sufficienti. Per i ripetitori, preferisco usare l'elemento di ancoraggio. Per usare l'elemento di ancoraggio, aggiornare l'elemento ItemTemplate di Repeater a:
<li>
<a href='ProductsForCategoryDetails.aspx?CategoryID=<%# Eval("CategoryID") %>'>
<%# Eval("CategoryName") %>
</a> - <%# Eval("Description") %>
</li>
Si noti che l'elemento CategoryID
può essere inserito direttamente all'interno dell'attributo dell'elemento di ancoraggio; tuttavia, a tale scopo, essere certi di delimitare il href
valore dell'attributo con apostrofi (e virgolette note) poiché il Eval
metodo all'interno href
dell'attributo href
delimita la stringa ("CategoryID"
) con virgolette. In alternativa, è possibile usare un controllo Web HyperLink:
<li>
<asp:HyperLink runat="server" Text='<%# Eval("CategoryName") %>'
NavigateUrl='<%# "ProductsForCategoryDetails.aspx?CategoryID=" &
Eval("CategoryID") %>'>
</asp:HyperLink>
- <%# Eval("Description") %>
</li>
Si noti come la parte statica dell'URL , ProductsForCategoryDetails.aspx?CategoryID
aggiunta al risultato direttamente Eval("CategoryID")
all'interno della sintassi di associazione dati usando la concatenazione stringa.
Un vantaggio dell'uso del controllo HyperLink è che può essere accessibile a livello di codice dal gestore eventi ItemDataBound
di Repeater, se necessario. Ad esempio, è possibile visualizzare il nome della categoria come testo anziché come collegamento per le categorie senza prodotti associati. Tale controllo potrebbe essere eseguito a livello di codice nel ItemDataBound
gestore eventi. Per le categorie senza prodotti associati, la proprietà HyperLink NavigateUrl
potrebbe essere impostata su una stringa vuota, causando così il rendering di tale nome di categoria come testo normale anziché come collegamento. Per altre informazioni sulla formattazione del contenuto di DataList e Ripetitore in base ai dati , vedere l'esercitazione Formattazione del contenuto di DataList e Repeater in base alla logica programmatica tramite il ItemDataBound
gestore eventi.
Se si segue, è possibile usare l'elemento di ancoraggio o l'approccio di controllo HyperLink nella pagina. Indipendentemente dall'approccio, quando si visualizza la pagina tramite un browser ogni nome di categoria deve essere eseguito il rendering come collegamento a ProductsForCategoryDetails.aspx
, passando il valore applicabile CategoryID
(vedere la figura 3).
Figura 3: I nomi delle categorie a cui si collega (fare clic per visualizzare l'immagine a dimensioni complete)ProductsForCategoryDetails.aspx
Passaggio 3: Elencare i prodotti appartenenti alla categoria selezionata
Con il completamento della pagina, siamo pronti a richiamare l'attenzione sull'implementazione della CategoryListMaster.aspx
pagina ProductsForCategoryDetails.aspx
"dettagli", . Aprire questa pagina, trascinare un oggetto DataList dalla casella degli strumenti nella Designer e impostarne la ID
proprietà su ProductsInCategory
. Successivamente, dallo smart tag di DataList scegliere di aggiungere un nuovo OggettoDataSource alla pagina, assegnando la denominazione ProductsInCategoryDataSource
a . Configurarla in modo che chiami il ProductsBLL
metodo della GetProductsByCategoryID(categoryID)
classe; impostare gli elenchi a discesa nelle schede INSERT, UPDATE e DELETE su (Nessuno).
Figura 4: Configurare ObjectDataSource per usare il metodo della GetProductsByCategoryID(categoryID)
classe (fare clic per visualizzare l'immagineProductsBLL
full-size)
Poiché il metodo accetta un parametro di input (categoryID
), la GetProductsByCategoryID(categoryID)
procedura guidata Scegli origine dati offre l'opportunità di specificare l'origine del parametro. Impostare l'origine del parametro su QueryString usando QueryStringField CategoryID
.
Figura 5: Usare il campo CategoryID
Querystring come origine del parametro (fare clic per visualizzare l'immagine full-size)
Come illustrato nelle esercitazioni precedenti, dopo aver completato la procedura guidata Scegli origine dati, Visual Studio crea automaticamente un ItemTemplate
oggetto per DataList che elenca ogni nome e valore del campo dati. Sostituire questo modello con uno che elenca solo il nome, il fornitore e il prezzo del prodotto. Impostare anche la proprietà di RepeatColumns
DataList su 2. Dopo queste modifiche, il markup dichiarativo di DataList e ObjectDataSource dovrebbe essere simile al seguente:
<asp:DataList ID="ProductsInCategory" runat="server" DataKeyField="ProductID"
RepeatColumns="2" DataSourceID="ProductsInCategoryDataSource"
EnableViewState="False">
<ItemTemplate>
<h5><%# Eval("ProductName") %></h5>
<p>
Supplied by <%# Eval("SupplierName") %><br />
<%# Eval("UnitPrice", "{0:C}") %>
</p>
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ProductsInCategoryDataSource"
OldValuesParameterFormatString="original_{0}" runat="server"
SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
<SelectParameters>
<asp:QueryStringParameter Name="categoryID" QueryStringField="CategoryID"
Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
Per visualizzare questa pagina in azione, iniziare dalla pagina. Fare clic su un collegamento nell'elenco CategoryListMaster.aspx
puntato categorie. In questo modo si porterà a ProductsForCategoryDetails.aspx
, passando lungo la CategoryID
querystring. ObjectDataSource ProductsInCategoryDataSource
in ProductsForCategoryDetails.aspx
otterrà quindi solo i prodotti per la categoria specificata e li visualizzerà in DataList, che esegue il rendering di due prodotti per riga. La figura 6 mostra uno screenshot di ProductsForCategoryDetails.aspx
quando si visualizzano le bevande.
Figura 6: Le bevande vengono visualizzate, due per riga (fare clic per visualizzare l'immagine a dimensioni complete)
Passaggio 4: Visualizzazione delle informazioni sulle categorie in ProductsForCategoryDetails.aspx
Quando un utente fa clic su una categoria in CategoryListMaster.aspx
, vengono presi in ProductsForCategoryDetails.aspx
e visualizzati i prodotti che appartengono alla categoria selezionata. Tuttavia, in ProductsForCategoryDetails.aspx
non ci sono segnali visivi come a quale categoria è stata selezionata. Un utente che voleva fare clic su Bevande, ma accidentalmente fatto clic su Condimenti, non ha modo di capire il loro errore dopo aver raggiunto ProductsForCategoryDetails.aspx
. Per alleviare questo potenziale problema, è possibile visualizzare informazioni sulla categoria selezionata , il nome e la descrizione, nella parte superiore della ProductsForCategoryDetails.aspx
pagina.
A tale scopo, aggiungere un controllo FormView sopra il controllo Ripetitore in ProductsForCategoryDetails.aspx
. Aggiungere quindi un nuovo OggettoDataSource alla pagina dallo smart tag di FormView denominato CategoryDataSource
e configurarlo per usare il CategoriesBLL
metodo della GetCategoryByCategoryID(categoryID)
classe.
Figura 7: Accedere alle informazioni sulla categoria tramite il CategoriesBLL
metodo della GetCategoryByCategoryID(categoryID)
classe (fare clic per visualizzare l'immagine full-size)
Come per ProductsInCategoryDataSource
ObjectDataSource aggiunto al passaggio 3, la CategoryDataSource
procedura guidata Configura origine dati richiede un'origine per il GetCategoryByCategoryID(categoryID)
parametro di input del metodo. Usare le stesse impostazioni di prima, impostando l'origine del parametro su QueryString e il valore QueryStringField su CategoryID
(fare riferimento alla figura 5).
Dopo aver completato la procedura guidata, Visual Studio crea automaticamente un ItemTemplate
oggetto , EditItemTemplate
e InsertItemTemplate
per FormView. Poiché si fornisce un'interfaccia di sola lettura, è possibile rimuovere e EditItemTemplate
InsertItemTemplate
. Inoltre, è possibile personalizzare l'oggetto FormView.ItemTemplate
Dopo aver rimosso i modelli superflui e personalizzando ItemTemplate, il markup dichiarativo di FormView e ObjectDataSource dovrebbe essere simile al seguente:
<asp:FormView ID="FormView1" runat="server" DataKeyNames="CategoryID"
DataSourceID="CategoryDataSource" EnableViewState="False" Width="100%">
<ItemTemplate>
<h3>
<asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Bind("CategoryName") %>' />
</h3>
<p>
<asp:Label ID="DescriptionLabel" runat="server"
Text='<%# Bind("Description") %>' />
</p>
</ItemTemplate>
</asp:FormView>
<asp:ObjectDataSource ID="CategoryDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategoryByCategoryID" TypeName="CategoriesBLL">
<SelectParameters>
<asp:QueryStringParameter Name="categoryID" Type="Int32"
QueryStringField="CategoryID" />
</SelectParameters>
</asp:ObjectDataSource>
La figura 8 mostra una schermata durante la visualizzazione di questa pagina tramite un browser.
Nota
Oltre a FormView, ho aggiunto anche un controllo HyperLink sopra FormView che restituirà l'utente all'elenco di categorie (CategoryListMaster.aspx
). È possibile posizionare questo collegamento altrove o o ometterlo completamente.
Figura 8: Le informazioni sulle categorie sono ora visualizzate nella parte superiore della pagina (fare clic per visualizzare l'immagine a dimensioni complete)
Passaggio 5: Visualizzazione di un messaggio se nessun prodotto appartiene alla categoria selezionata
La CategoryListMaster.aspx
pagina elenca tutte le categorie nel sistema, indipendentemente dal fatto che siano presenti prodotti associati. Se un utente fa clic su una categoria senza prodotti associati, il rendering di DataList in ProductsForCategoryDetails.aspx
non verrà eseguito, perché l'origine dati non includerà alcun elemento. Come illustrato nelle esercitazioni precedenti, GridView fornisce una EmptyDataText
proprietà che può essere usata per specificare un messaggio di testo da visualizzare se non sono presenti record nell'origine dati. Sfortunatamente, né DataList né Repeater hanno una proprietà di questo tipo.
Per visualizzare un messaggio che informa l'utente che non sono presenti prodotti corrispondenti per la categoria selezionata, è necessario aggiungere un controllo Etichetta alla pagina la cui Text
proprietà è assegnata al messaggio da visualizzare nel caso in cui non siano presenti prodotti corrispondenti. È quindi necessario impostare la relativa Visible
proprietà a livello di codice in base al fatto che DataList contenga o meno elementi.
A tale scopo, iniziare aggiungendo un'etichetta sotto l'oggetto DataList. Impostare la relativa ID
proprietà su NoProductsMessage
e la relativa Text
proprietà su "There are no products for the selected category..." (Nessun prodotto per la categoria selezionata...) Successivamente, è necessario impostare a livello di codice la proprietà di Visible
questa etichetta in base al fatto che i dati siano stati associati o meno a ProductsInCategory
DataList. Questa assegnazione deve essere eseguita dopo che i dati sono stati associati a DataList. Per GridView, DetailsView e FormView, è possibile creare un gestore eventi per l'evento del controllo, che viene generato dopo il completamento dell'associazione DataBound
dati. Tuttavia, né DataList né Repeater dispone di un DataBound
evento disponibile.
Per questo particolare esempio è possibile assegnare la proprietà dell'etichetta Visible
nel Page_Load
gestore eventi, poiché i dati saranno stati assegnati a DataList prima dell'evento della Load
pagina. Tuttavia, questo approccio non funziona nel caso generale, perché i dati di ObjectDataSource potrebbero essere associati a DataList più avanti nel ciclo di vita della pagina. Ad esempio, se i dati visualizzati sono basati sul valore in un altro controllo, ad esempio quando si visualizza un report master/dettaglio utilizzando un oggetto DropDownList per contenere i record "master", i dati potrebbero non essere rimbalzati al controllo Web dati fino alla PreRender
fase del ciclo di vita della pagina.
Una soluzione che funzionerà per tutti i casi consiste nell'assegnare la Visible
proprietà a False
nel gestore eventi (o ItemCreated
) di ItemDataBound
DataList quando si associa un tipo di elemento di Item
o AlternatingItem
. In questo caso si sa che nell'origine dati è presente almeno un elemento di dati e quindi può nascondere l'etichetta NoProductsMessage
. Oltre a questo gestore eventi, è necessario anche un gestore eventi per l'evento di DataBinding
DataList, in cui si inizializza la proprietà dell'etichetta Visible
su True
. Poiché l'evento DataBinding
viene generato prima degli ItemDataBound
eventi, la proprietà dell'etichetta Visible
verrà inizialmente impostata su True
; se sono presenti elementi di dati, tuttavia, verrà impostata su False
. Il codice seguente implementa questa logica:
protected void ProductsInCategory_DataBinding(object sender, EventArgs e)
{
// Show the Label
NoProductsMessage.Visible = true;
}
protected void ProductsInCategory_ItemDataBound(object sender, DataListItemEventArgs e)
{
// If we have a data item, hide the Label
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
NoProductsMessage.Visible = false;
}
Tutte le categorie nel database Northwind sono associate a uno o più prodotti. Per testare questa funzionalità, ho modificato manualmente il database Northwind per questa esercitazione, riassegnando tutti i prodotti associati alla categoria Produce (CategoryID
= 7) alla categoria Pesce ( =CategoryID
8). Questa operazione può essere eseguita da Esplora server scegliendo Nuova query e usando l'istruzione seguente UPDATE
:
UPDATE Products SET
CategoryID = 8
WHERE CategoryID = 7
Dopo aver aggiornato il database di conseguenza, tornare alla CategoryListMaster.aspx
pagina e fare clic sul collegamento Produce. Poiché non sono più presenti prodotti appartenenti alla categoria Produce, verrà visualizzato il messaggio "Non ci sono prodotti per la categoria selezionata..." messaggio, come illustrato nella figura 9.
Figura 9: Viene visualizzato un messaggio se non sono presenti prodotti appartenenti alla categoria selezionata (fare clic per visualizzare l'immagine a dimensione intera)
Riepilogo
Anche se i report master/dettagli possono visualizzare sia i record master che i record di dettaglio in una singola pagina, in molti siti Web sono separati tra due pagine Web. In questa esercitazione è stato illustrato come implementare un report master/dettaglio con le categorie elencate in un elenco puntato usando un ripetitore nella pagina Web "master" e i prodotti associati elencati nella pagina "dettagli". Ogni voce di elenco nella pagina Web master contiene un collegamento alla pagina dei dettagli passata lungo il valore della CategoryID
riga.
Nella pagina dei dettagli il recupero di tali prodotti per il fornitore specificato è stato eseguito tramite il ProductsBLL
metodo della GetProductsByCategoryID(categoryID)
classe. Il valore del categoryID
parametro è stato specificato in modo dichiarativo usando il CategoryID
valore querystring come origine del parametro. Abbiamo anche esaminato come visualizzare i dettagli delle categorie nella pagina dei dettagli usando un controllo FormView e come visualizzare un messaggio se non sono presenti prodotti appartenenti alla categoria selezionata.
Buon programmatori!
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, lavora con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto all'indirizzo mitchell@4GuysFromRolla.com. o tramite il suo blog, disponibile all'indirizzo http://ScottOnWriting.NET.
Grazie speciale...
Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali di questa esercitazione erano Zack Jones e Liz Shulok. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per