Applicazione di filtri al report master o di dettaglio usando due controlli DropDownList (C#)

di Scott Mitchell

Scarica il PDF

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 Customerstabelle , Orderse 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à Categoriessu e quindi fare clic sul collegamento Configura origine dati nello smart tag. Nella Configurazione guidata origine dati scegliere di aggiungere una nuova origine dati.

Aggiungere una nuova origine dati per l'elenco a discesa

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() .

Scegliere di usare la classe CategoriesBLL

Figura 2: Scegliere di usare la classe (fare clic per visualizzare l'immagineCategoriesBLL a dimensione intera)

Configurare ObjectDataSource per l'uso del metodo GetCategories()

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.

Fare in modo che DropDownList visualizzi il campo CategoryName e usi CategoryID come valore

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.

Abilitare AutoPostBack per l'elenco a discesa Categorie

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.

Aggiungere una nuova origine dati per l'elenco a discesa ProductsByCategory

Figura 6: Aggiungere una nuova origine dati per l'elenco ProductsByCategory a discesa (fare clic per visualizzare l'immagine a dimensione intera)

Creare un nuovo objectDataSource denominato ProductsByCategoryDataSource

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 .

Screenshot della finestra Configura origine dati - productsByCategoryDataSource con ProductsBLL selezionato e il pulsante Avanti evidenziato.

Figura 8: Scegliere di usare la classe (fare clic per visualizzare l'immagineProductsBLL a dimensione intera)

Configurare ObjectDataSource per l'uso del metodo GetProductsByCategoryID(categoryID)

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.

Eseguire il pull del valore del parametro categoryID dall'elenco a discesa Categorie

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.

Specificare i campi origine dati utilizzati per le proprietà Text e Value di ListItems dell'oggetto DropDownList

Figura 11: Specificare i campi origine dati usati per le proprietà e Value le proprietà dell'elenco TextListItem 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.

Quando si visita per la prima volta la pagina, la categoria Bevande è selezionata

Figura 12: Quando si visita per la prima volta la pagina, la categoria Bevande è selezionata (fare clic per visualizzare l'immagine a dimensione intera)

La scelta di una categoria diversa consente di visualizzare i prodotti della nuova categoria

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.

Abilitare la funzionalità AutoPostBack per i prodottiByCategory 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à ProductDetailssu 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 .

Screenshot della finestra Configura origine dati - productsByCategoryDataSource in cui è selezionato ProductsBLL e il pulsante Avanti è evidenziato.

Figura 15: Scegliere di usare la classe (fare clic per visualizzare l'immagineProductsBLL a dimensione intera)

Configurare ObjectDataSource per l'uso del metodo GetProductByProductID(productID)

Figura 16: Configurare ObjectDataSource per l'uso del metodo (fare clic per visualizzare l'immagineGetProductByProductID(productID) a dimensione intera)

Eseguire il pull del valore del parametro productID dall'elenco a discesa ProductsByCategory

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 ProductIDcampi , SupplierIDe 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.

I dettagli del prodotto selezionato vengono visualizzati in un controllo DetailsView

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.

I dettagli del prodotto selezionato in precedenza sono ancora visualizzati

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.

Il valore dell'elenco a discesa ProductsByCategory cambia dopo che il controllo ObjectDataSource di ProductDetails DetailsView verifica la presenza di modifiche

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 ProductsByCategoryDataBound 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.

ProductDetails DetailsView viene aggiornato in modo esplicito quando viene generato l'evento DataBoundList di ProductsByCategory

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.