Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione espande la relazione master/dettaglio per aggiungere un terzo livello, usando due controlli DropDownList per selezionare i record padre e nonni desiderati.
Introduzione
Nell'esercitazione precedente è stato illustrato come visualizzare un semplice report master/dettagli usando un singolo elenco DropDownList popolato con le categorie e un controllo GridView che mostra i prodotti che appartengono alla categoria selezionata. Questo modello di report funziona correttamente durante la visualizzazione di record con una relazione uno-a-molti e può essere facilmente esteso per gli scenari che includono più relazioni uno-a-molti. Ad esempio, un sistema di immissione degli ordini include tabelle che corrispondono a clienti, ordini ed elementi delle righe degli ordini. Un determinato cliente può avere più ordini con ogni ordine costituito da più articoli. Tali dati possono essere presentati all'utente con due DropDownList e un controllo GridView. Il primo DropDownList avrà una voce di elenco per ogni cliente nel database con il contenuto del secondo che rappresenta gli ordini inseriti dal cliente selezionato. Un controllo GridView elenca le voci dell'ordine selezionato.
Anche se il database Northwind include le informazioni canoniche sui dettagli cliente/ordine/ordine nelle Customers
tabelle , Orders
e Order Details
, queste tabelle non vengono acquisite nell'architettura. Tuttavia, è comunque possibile illustrare l'uso di due DropDownList dipendenti. Il primo DropDownList elenca le categorie e il secondo i prodotti appartenenti alla categoria selezionata. Un controllo DetailsView elenca quindi i dettagli del prodotto selezionato.
Passaggio 1: Creazione e popolamento dell'elenco a discesa Categorie
Il primo obiettivo consiste nell'aggiungere l'elenco DropDownList che elenca le categorie. Questi passaggi sono stati esaminati in dettaglio nell'esercitazione precedente, ma sono riepilogati qui per completezza.
Aprire la MasterDetailsDetails.aspx
pagina nella Filtering
cartella, aggiungere un oggetto DropDownList alla pagina, impostarne ID
la proprietà Categories
su e quindi fare clic sul collegamento Configura origine dati nello smart tag. Nella Configurazione guidata origine dati scegliere di aggiungere una nuova origine dati.
Figura 1: Aggiungere una nuova origine dati per l'elenco a discesa (fare clic per visualizzare l'immagine a dimensione intera)
La nuova origine dati deve, naturalmente, essere ObjectDataSource. Denominare il nuovo ObjectDataSource CategoriesDataSource
e richiamare il CategoriesBLL
metodo dell'oggetto GetCategories()
.
Figura 2: Scegliere di usare la classe (fare clic per visualizzare l'immagineCategoriesBLL
a dimensione intera)
Figura 3: Configurare ObjectDataSource per l'uso del metodo (fare clic per visualizzare l'immagineGetCategories()
a dimensione intera)
Dopo aver configurato ObjectDataSource, è comunque necessario specificare il campo dell'origine dati da visualizzare in Categories
DropDownList e quale campo deve essere configurato come valore per l'elemento di elenco. Impostare il CategoryName
campo come visualizzazione e CategoryID
come valore per ogni elemento dell'elenco.
Figura 4: Fare in modo che l'elenco a discesa visualizzi il CategoryName
campo e usi CategoryID
come valore (fare clic per visualizzare l'immagine a dimensione intera)
A questo punto è disponibile un controllo DropDownList (Categories
) popolato con i record della Categories
tabella. Quando l'utente sceglie una nuova categoria da DropDownList, si vuole che venga eseguito un postback per aggiornare l'elenco a discesa del prodotto che verrà creato nel passaggio 2. Selezionare quindi l'opzione Abilita AutoPostBack dallo categories
smart tag dropDownList.
Figura 5: Abilitare AutoPostBack per l'elenco Categories
a discesa (fare clic per visualizzare l'immagine a dimensione intera)
Passaggio 2: Visualizzazione dei prodotti della categoria selezionata in un secondo elenco a discesa
Al termine dell'elenco Categories
DropDownList, il passaggio successivo consiste nel visualizzare un elenco a discesa di prodotti appartenenti alla categoria selezionata. A tale scopo, aggiungere un altro dropDownList alla pagina denominata ProductsByCategory
. Come per Categories
DropDownList, creare un nuovo ObjectDataSource per ProductsByCategory
DropDownList denominato ProductsByCategoryDataSource
.
Figura 6: Aggiungere una nuova origine dati per l'elenco ProductsByCategory
a discesa (fare clic per visualizzare l'immagine a dimensione intera)
Figura 7: Creare un nuovo oggettoDataSource denominato ProductsByCategoryDataSource
(fare clic per visualizzare l'immagine a dimensione intera)
ProductsByCategory
Poiché DropDownList deve visualizzare solo i prodotti appartenenti alla categoria selezionata, fare in modo che ObjectDataSource richiami il GetProductsByCategoryID(categoryID)
metodo dall'oggetto ProductsBLL
.
Figura 8: Scegliere di usare la classe (fare clic per visualizzare l'immagineProductsBLL
a dimensione intera)
Figura 9: Configurare ObjectDataSource per l'uso del metodo (fare clic per visualizzare l'immagineGetProductsByCategoryID(categoryID)
a dimensione intera)
Nel passaggio finale della procedura guidata è necessario specificare il valore del categoryID
parametro . Assegnare questo parametro all'elemento selezionato da Categories
DropDownList.
Figura 10: Eseguire il pull del valore del categoryID
parametro dall'elenco Categories
a discesa (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver configurato ObjectDataSource, tutto ciò che rimane consiste nel specificare i campi dell'origine dati usati per la visualizzazione e il valore degli elementi dropDownList. Visualizzare il ProductName
campo e usare il ProductID
campo come valore.
Figura 11: Specificare i campi origine dati usati per le proprietà e Value
le proprietà dell'elenco Text
ListItem
a discesa (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver configurato ObjectDataSource e ProductsByCategory
DropDownList, nella pagina verranno visualizzati due elenchi DropDownList: il primo elenca tutte le categorie mentre il secondo elenca i prodotti appartenenti alla categoria selezionata. Quando l'utente seleziona una nuova categoria dal primo DropDownList, verrà eseguito un postback e il secondo DropDownList verrà rimbalzato, mostrando i prodotti che appartengono alla categoria appena selezionata. Le figure 12 e 13 vengono visualizzate MasterDetailsDetails.aspx
in azione quando vengono visualizzate tramite un browser.
Figura 12: Quando si visita per la prima volta la pagina, la categoria Bevande è selezionata (fare clic per visualizzare l'immagine a dimensione intera)
Figura 13: La scelta di una categoria diversa visualizza i prodotti della nuova categoria (fare clic per visualizzare l'immagine a dimensione intera)
productsByCategory
Attualmente DropDownList, se modificato, non causa un postback. Tuttavia, si vuole che venga eseguito un postback dopo aver aggiunto un controllo DetailsView per visualizzare i dettagli del prodotto selezionato (passaggio 3). Selezionare quindi la casella di controllo Abilita AutoPostBack dallo productsByCategory
smart tag dropDownList.
Figura 14: Abilitare la funzionalità AutoPostBack per l'elenco productsByCategory
a discesa (fare clic per visualizzare l'immagine a dimensione intera)
Passaggio 3: Uso di un controllo DetailsView per visualizzare i dettagli per il prodotto selezionato
Il passaggio finale consiste nel visualizzare i dettagli per il prodotto selezionato in un controllo DetailsView. A tale scopo, aggiungere un controllo DetailsView alla pagina, impostarne la ID
proprietà ProductDetails
su e crearne uno nuovo ObjectDataSource. Configurare ObjectDataSource per eseguire il ProductsBLL
pull dei dati dal metodo della GetProductByProductID(productID)
classe usando il valore selezionato di ProductsByCategory
DropDownList per il valore del productID
parametro .
Figura 15: Scegliere di usare la classe (fare clic per visualizzare l'immagineProductsBLL
a dimensione intera)
Figura 16: Configurare ObjectDataSource per l'uso del metodo (fare clic per visualizzare l'immagineGetProductByProductID(productID)
a dimensione intera)
Figura 17: Eseguire il pull del valore del parametro dall'elenco ProductsByCategory
a discesa (fare clic per visualizzare l'immagineproductID
a dimensione intera)
È possibile scegliere di visualizzare uno dei campi disponibili in DetailsView. Si è scelto di rimuovere i ProductID
campi , SupplierID
e CategoryID
e riordinati e formattati i campi rimanenti. Inoltre, ho cancellato le proprietà e Width
di Height
DetailsView, consentendo a DetailsView di espandersi fino alla larghezza necessaria per visualizzare meglio i dati anziché limitarlo a una dimensione specificata. Di seguito è riportato il markup completo:
<asp:DetailsView ID="ProductDetails" runat="server"
AutoGenerateRows="False" DataKeyNames="ProductID"
DataSourceID="ObjectDataSource1" EnableViewState="False">
<Fields>
<asp:BoundField DataField="ProductName"
HeaderText="Product" SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName"
HeaderText="Category" ReadOnly="True"
SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName"
HeaderText="Supplier" ReadOnly="True"
SortExpression="SupplierName" />
<asp:BoundField DataField="QuantityPerUnit"
HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice"
DataFormatString="{0:c}" HeaderText="Price"
HtmlEncode="False" SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock"
HeaderText="UnitsInStock" SortExpression="Units In Stock" />
<asp:BoundField DataField="UnitsOnOrder"
HeaderText="UnitsOnOrder" SortExpression="Units On Order" />
<asp:BoundField DataField="ReorderLevel"
HeaderText="ReorderLevel" SortExpression="Reorder Level" />
<asp:CheckBoxField DataField="Discontinued"
HeaderText="Discontinued" SortExpression="Discontinued" />
</Fields>
</asp:DetailsView>
Provare la MasterDetailsDetails.aspx
pagina in un browser. A prima vista può sembrare che tutto funzioni come desiderato, ma c'è un problema sottile. Quando si sceglie una nuova categoria, ProductsByCategory
DropDownList viene aggiornata in modo da includere tali prodotti per la categoria selezionata, ma DetailsView ProductDetails
continua a mostrare le informazioni sul prodotto precedenti. DetailsView viene aggiornato quando si sceglie un prodotto diverso per la categoria selezionata. Inoltre, se si esegue un test abbastanza approfondito, si noterà che se si scelgono continuamente nuove categorie (ad esempio scegliendo Bevande da Categories
DropDownList, condimenti, quindi confezioni) ogni altra selezione di categoria fa ProductDetails
sì che DetailsView venga aggiornato.
Per contribuire a concretizzare questo problema, si esamini un esempio specifico. Quando si visita per la prima volta la pagina viene selezionata la categoria Bevande e i prodotti correlati vengono caricati nell'elenco ProductsByCategory
DropDownList. Chai è il prodotto selezionato e i relativi dettagli vengono visualizzati in ProductDetails
DetailsView, come illustrato nella figura 18.
Figura 18: I dettagli del prodotto selezionato vengono visualizzati in un controllo DetailsView (fare clic per visualizzare un'immagine a dimensione intera)
Se si modifica la selezione della categoria da Bevande a Condimenti, viene eseguito un postback e l'elenco ProductsByCategory
DropDownList viene aggiornato di conseguenza, ma DetailsView visualizza comunque i dettagli per Chai.
Figura 19: I dettagli del prodotto selezionato in precedenza sono ancora visualizzati (fare clic per visualizzare l'immagine a dimensione intera)
La selezione di un nuovo prodotto dall'elenco aggiorna DetailsView come previsto. Se si seleziona una nuova categoria dopo aver modificato il prodotto, detailsView non verrà aggiornato di nuovo. Tuttavia, se invece di scegliere un nuovo prodotto è stata selezionata una nuova categoria, detailsView verrà aggiornato. Cosa sta succedendo qui al mondo?
Il problema è un problema di temporizzazione nel ciclo di vita della pagina. Ogni volta che viene richiesta una pagina, viene eseguita una serie di passaggi durante il rendering. In uno di questi passaggi i controlli ObjectDataSource controllano se uno dei relativi SelectParameters
valori è stato modificato. In tal caso, il controllo Web dati associato a ObjectDataSource sa che deve aggiornarne la visualizzazione. Ad esempio, quando viene selezionata una nuova categoria, ProductsByCategoryDataSource
ObjectDataSource rileva che i relativi valori dei parametri sono stati modificati e ProductsByCategory
dropDownList viene riassociato, ottenendo i prodotti per la categoria selezionata.
Il problema che si verifica in questa situazione è che il punto del ciclo di vita della pagina verificato da ObjectDataSources per verificare la presenza di parametri modificati si verifica prima del riassociamento dei controlli Web dati associati. Pertanto, quando si seleziona una nuova categoria ProductsByCategoryDataSource
, ObjectDataSource rileva una modifica nel valore del parametro. ObjectDataSource usato da ProductDetails
DetailsView, tuttavia, non annota tali modifiche perché ProductsByCategory
DropDownList deve ancora essere rimbalzato. Più avanti nel ciclo di vita, ProductsByCategory
DropDownList viene riassociato a ObjectDataSource, afferrando i prodotti per la categoria appena selezionata. Mentre il ProductsByCategory
valore di DropDownList è stato modificato, il ProductDetails
controllo ObjectDataSource di DetailsView ha già eseguito il controllo del valore del parametro. Di conseguenza, DetailsView visualizza i risultati precedenti. Questa interazione è illustrata nella figura 20.
Figura 20: Il ProductsByCategory
valore dell'elenco a discesa cambia dopo il controllo ObjectDataSource di DetailsView verifica la presenza di modifiche (fare clic per visualizzare l'immagineProductDetails
a dimensione intera)
Per risolvere questo problema, è necessario riassociare in modo esplicito detailsView ProductDetails
dopo l'associazione ProductsByCategory
di DropDownList. A tale scopo, è possibile chiamare il ProductDetails
metodo detailsView DataBind()
quando viene generato l'evento ProductsByCategory
DataBound
dropDownList. Aggiungere il codice del gestore eventi seguente alla MasterDetailsDetails.aspx
classe code-behind della pagina (fare riferimento a "Impostazione a livello di codice dei valori dei parametri di ObjectDataSource" per una discussione su come aggiungere un gestore eventi):
protected void ProductsByCategory_DataBound(object sender, EventArgs e)
{
ProductDetails.DataBind();
}
Dopo aver aggiunto questa ProductDetails
chiamata esplicita al metodo detailsView DataBind()
, l'esercitazione funziona come previsto. La figura 21 evidenzia il modo in cui questa modifica ha risolto il problema precedente.
Figura 21: DetailsView ProductDetails
viene aggiornato in modo esplicito quando viene generato l'evento ProductsByCategory
dell'elenco DataBound
a discesa (fare clic per visualizzare l'immagine a dimensione intera)
Riepilogo
DropDownList funge da elemento dell'interfaccia utente ideale per i report master/dettagli in cui esiste una relazione uno-a-molti tra i record master e di dettaglio. Nell'esercitazione precedente è stato illustrato come usare un singolo oggetto DropDownList per filtrare i prodotti visualizzati dalla categoria selezionata. In questa esercitazione è stato sostituito GridView dei prodotti con un oggetto DropDownList e è stato usato un controllo DetailsView per visualizzare i dettagli del prodotto selezionato. I concetti illustrati in questa esercitazione possono essere facilmente estesi ai modelli di dati che coinvolgono più relazioni uno-a-molti, ad esempio clienti, ordini ed elementi degli ordini. In generale, è sempre possibile aggiungere un oggetto DropDownList per ognuna delle entità "una" nelle relazioni uno-a-molti.
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 a
Questa serie di esercitazioni è stata esaminata da molti revisori utili. Il revisore principale di questa esercitazione era Hilton Giesenow. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.