Report master o di dettaglio con un elenco puntato di record master e un controllo DataList di dettagli (VB)
In questa esercitazione verrà compresso il report master/dettaglio a due pagine dell'esercitazione precedente in una singola pagina, che mostra un elenco puntato di nomi di categoria sul lato sinistro dello schermo e i prodotti della categoria selezionati a destra dello schermo.
Introduzione
Nell'esercitazione precedente è stato illustrato come separare un report master/dettaglio tra due pagine. Nella pagina master è stato usato un controllo Repeater per eseguire il rendering di un elenco puntato di categorie. Ogni nome di categoria è un collegamento ipertestuale che, quando si fa clic, consente all'utente di accedere alla pagina dei dettagli, in cui un DataList a due colonne mostra tali prodotti appartenenti alla categoria selezionata.
In questa esercitazione si comprimerà l'esercitazione a due pagine in una singola pagina, che mostra un elenco puntato di nomi di categoria sul lato sinistro della schermata con ogni nome di categoria sottoposto a rendering come LinkButton. Facendo clic su uno dei nomi di categoria LinkButtons si induce un postback e associa i prodotti della categoria selezionata a un oggetto DataList a due colonne a destra della schermata. Oltre a visualizzare ogni nome di categoria, il ripetitore a sinistra mostra il numero di prodotti totali per una determinata categoria (vedere la figura 1).
Figura 1: Il nome della categoria e il numero totale di prodotti vengono visualizzati a sinistra (fare clic per visualizzare l'immagine full-size)
Passaggio 1: Visualizzazione di un ripetitore nella parte sinistra dello schermo
Per questa esercitazione è necessario visualizzare l'elenco puntato delle categorie a sinistra dei prodotti della categoria selezionata. Il contenuto all'interno di una pagina Web può essere posizionato usando tag di paragrafo di elementi HTML standard, spazi di interruzione, <table>
s e così via o tramite tecniche CSS (StyleSheet) a catena. Tutte le esercitazioni finora hanno usato tecniche CSS per la posizionamento. Quando è stata creata l'interfaccia utente di spostamento nella pagina master nell'esercitazione Master Pages and Site Navigation è stata usata la posizione assoluta, che indica l'offset di pixel preciso per l'elenco di spostamento e il contenuto principale. In alternativa, CSS può essere usato per posizionare un elemento a destra o a sinistra di un altro tramite spostamento mobile. È possibile visualizzare l'elenco puntato di categorie a sinistra dei prodotti della categoria selezionata mobilendo il ripetitore a sinistra di DataList
Aprire la CategoriesAndProducts.aspx
pagina dalla DataListRepeaterFiltering
cartella e aggiungere alla pagina un ripetitore e un oggetto DataList. Impostare Il ripetitore su e l'oggetto ID
Categories
DataList s su CategoryProducts
. Passare alla visualizzazione Origine e inserire i controlli Repeater e DataList all'interno dei propri <div>
elementi. Ovvero, racchiudere il Ripetitore all'interno di un <div>
elemento prima e quindi DataList nel proprio <div>
elemento direttamente dopo il Ripetitore. Il markup a questo punto dovrebbe essere simile al seguente:
<div>
<asp:Repeater ID="Categories" runat="server">
</asp:Repeater>
</div>
<div>
<asp:DataList ID="CategoryProducts" runat="server">
</asp:DataList>
</div>
Per float il ripetitore a sinistra di DataList, è necessario usare l'attributo float
di stile CSS, ad esempio:
<div>
Repeater
</div>
<div>
DataList
</div>
Il float: left;
valore float del primo <div>
elemento a sinistra del secondo. Le width
impostazioni e padding-right
indicano la prima <div>
width
s e la quantità di riempimento aggiunta tra il contenuto dell'elemento e il <div>
relativo margine destro. Per altre informazioni sugli elementi mobili in CSS, vedere Floatutorial.
Anziché specificare l'impostazione dello stile direttamente tramite l'attributo del style
primo <p>
elemento, consente di creare invece una nuova classe CSS in Styles.css
denominata FloatLeft
:
.FloatLeft
{
float: left;
width: 33%;
padding-right: 10px;
}
È quindi possibile sostituire l'oggetto <div>
con <div class="FloatLeft">
.
Dopo aver aggiunto la classe CSS e configurato il markup nella CategoriesAndProducts.aspx
pagina, passare alla Designer. Verrà visualizzata la spostamento del ripetitore a sinistra dell'oggetto DataList(anche se ora entrambe appaiono come caselle grigie poiché è ancora stato configurato le origini dati o i modelli).
Figura 2: Il ripetitore viene float a sinistra dell'elenco dati (fare clic per visualizzare l'immagine a dimensioni complete)
Passaggio 2: Determinazione del numero di prodotti per ogni categoria
Con il completamento del markup Repeater e DataList, è possibile associare i dati della categoria al controllo Ripetitore. Tuttavia, come illustrato nell'elenco puntato delle categorie nella figura 1, oltre a ogni nome di categoria è necessario visualizzare anche il numero di prodotti associati alla categoria. Per accedere a queste informazioni, è possibile:
- Determinare queste informazioni dalla classe code-behind della pagina ASP.NET. Dato un particolare
categoryID
è possibile determinare il numero di prodotti associati chiamando ilProductsBLL
metodo dellaGetProductsByCategoryID(categoryID)
classe. Questo metodo restituisce unProductsDataTable
oggetto la cuiCount
proprietà indicaProductsRow
il numero di prodotti presenti, ovvero il numero di prodotti per l'oggetto specificatocategoryID
. È possibile creare unItemDataBound
gestore eventi per il ripetitore che, per ogni categoria associata al ripetitore, chiama il metodo dellaGetProductsByCategoryID(categoryID)
classe e include ilProductsBLL
relativo conteggio nell'output. - Aggiornare nell'oggetto
CategoriesDataTable
DataSet tipizzato per includere unaNumberOfProducts
colonna. È quindi possibile aggiornare ilGetCategories()
metodo inCategoriesDataTable
per includere queste informazioni o, in alternativa, lasciareGetCategories()
come è e creare un nuovoCategoriesDataTable
metodo denominatoGetCategoriesAndNumberOfProducts()
.
Esplora entrambe queste tecniche. Il primo approccio è più semplice da implementare perché non è necessario aggiornare il livello di accesso ai dati; tuttavia, richiede più comunicazioni con il database. La chiamata al ProductsBLL
metodo della GetProductsByCategoryID(categoryID)
classe nel ItemDataBound
gestore eventi aggiunge una chiamata di database aggiuntiva per ogni categoria visualizzata nel ripetitore. Con questa tecnica sono disponibili chiamate di database N + 1, dove N è il numero di categorie visualizzate nel ripetitore. Con il secondo approccio, il conteggio dei prodotti viene restituito con informazioni su ogni categoria del metodo (GetCategories()
o GetCategoriesAndNumberOfProducts()
) della CategoriesBLL
classe, causando così un solo viaggio nel database.
Determinazione del numero di prodotti nel gestore eventi ItemDataBound
Determinare il numero di prodotti per ogni categoria nel gestore eventi ItemDataBound
ripetitore non richiede modifiche al livello di accesso ai dati esistente. Tutte le modifiche possono essere apportate direttamente all'interno della CategoriesAndProducts.aspx
pagina. Iniziare aggiungendo un nuovo oggetto ObjectDataSource denominato CategoriesDataSource
tramite lo smart tag di Repeater. Configurare CategoriesDataSource
quindi ObjectDataSource in modo che recupera i dati dal CategoriesBLL
metodo della GetCategories()
classe.
Figura 3: Configurare ObjectDataSource per usare il metodo della GetCategories()
classe (fare clic per visualizzare l'immagineCategoriesBLL
full-size)
Ogni elemento nel Categories
ripetitore deve essere selezionabile e, quando si fa clic, causa la visualizzazione di CategoryProducts
Tali prodotti per la categoria selezionata. Questa operazione può essere eseguita eseguendo un collegamento ipertestuale a ogni categoria, collegandosi alla stessa pagina (CategoriesAndProducts.aspx
), ma passando la CategoryID
querystring, molto simile a quella illustrata nell'esercitazione precedente. Il vantaggio di questo approccio è che una pagina che visualizza un determinato prodotto di categoria può essere segnalibro e indicizzato da un motore di ricerca.
In alternativa, è possibile creare ogni categoria un LinkButton, ovvero l'approccio che verrà usato per questa esercitazione. LinkButton esegue il rendering nel browser dell'utente come collegamento ipertestuale ma, quando si fa clic, induce un postback; nel postback, l'oggetto ObjectDataSource di DataList deve essere aggiornato per visualizzare i prodotti appartenenti alla categoria selezionata. Per questa esercitazione, l'uso di un collegamento ipertestuale ha più senso rispetto all'uso di un LinkButton; tuttavia, potrebbero esserci altri scenari in cui l'uso di un LinkButton è più vantaggioso. Sebbene l'approccio ai collegamenti ipertestuali sia ideale per questo esempio, è possibile esplorare usando LinkButton. Come si vedrà, l'uso di un LinkButton introduce alcune sfide che altrimenti non si verificano con un collegamento ipertestuale. Pertanto, l'uso di un LinkButton in questa esercitazione evidenzia queste sfide e fornisce soluzioni per tali scenari in cui è possibile usare un LinkButton anziché un collegamento ipertestuale.
Nota
È consigliabile ripetere questa esercitazione usando un controllo HyperLink o <a>
un elemento al posto di LinkButton.
Il markup seguente mostra la sintassi dichiarativa per Il ripetitore e ObjectDataSource. Si noti che i modelli di Ripetitore eseguono il rendering di un elenco puntato con ogni elemento come LinkButton:
<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:LinkButton runat="server" ID="ViewCategory"></asp:LinkButton></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
Nota
Per questa esercitazione il ripetitore deve disporre del relativo stato di visualizzazione abilitato (notare l'omissione EnableViewState="False"
della sintassi dichiarativa del ripetitore). Nel passaggio 3 verrà creato un gestore eventi per l'evento Repeater ItemCommand
in cui si aggiornerà l'insieme ObjectDataSource di DataList.SelectParameters
Il ripetitore s, tuttavia, non verrà attivato se lo stato di ItemCommand
visualizzazione è disabilitato.
LinkButton con il ID
valore della proprietà di ViewCategory
non ha il relativo Text
set di proprietà. Se avessimo appena voluto visualizzare il nome della categoria, avremmo impostato la proprietà Text dichiarativamente, tramite la sintassi databinding, come segue:
<asp:LinkButton runat="server" ID="ViewCategory"
Text='<%# Eval("CategoryName") %>' />
Tuttavia, si vuole visualizzare sia il nome della categoria che il numero di prodotti appartenenti a tale categoria. Queste informazioni possono essere recuperate dal gestore eventi del ripetitore eseguendo una chiamata al ProductBLL
metodo della ItemDataBound
GetCategoriesByProductID(categoryID)
classe e determinando il numero di record restituiti nell'oggetto ProductsDataTable
risultante, come illustrato nel codice seguente:
Protected Sub Categories_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
' Make sure we're working with a data item...
If e.Item.ItemType = ListItemType.Item OrElse _
e.Item.ItemType = ListItemType.AlternatingItem Then
' Reference the CategoriesRow instance bound to this RepeaterItem
Dim category As Northwind.CategoriesRow = _
CType(CType(e.Item.DataItem, System.Data.DataRowView).Row, _
Northwind.CategoriesRow)
' Determine how many products are in this category
Dim productsAPI As New NorthwindTableAdapters.ProductsTableAdapter
Dim productCount As Integer = _
productsAPI.GetProductsByCategoryID(category.CategoryID).Count
' Reference the ViewCategory LinkButton and set its Text property
Dim ViewCategory As LinkButton = _
CType(e.Item.FindControl("ViewCategory"), LinkButton)
ViewCategory.Text = _
String.Format("{0} ({1:N0})", category.CategoryName, productCount)
End If
End Sub
Si inizia assicurandosi di lavorare con un elemento di dati (uno il cui ItemType
è Item
o AlternatingItem
) e quindi fare riferimento all'istanza appena associata all'oggetto CategoriesRow
corrente RepeaterItem
. Si determina quindi il numero di prodotti per questa categoria creando un'istanza ProductsBLL
della classe, chiamando il GetCategoriesByProductID(categoryID)
relativo metodo e determinando il numero di record restituiti usando la Count
proprietà . Infine, linkButton nell'elementoTemplate è riferimento e la ViewCategory
relativa Text
proprietà è impostata su CategoryName (NumberOfProductsInCategory), dove NumberOfProductsInCategory viene formattato come numero con valori decimali zero.
Nota
In alternativa, è possibile aggiungere una funzione di formattazione alla classe code-behind della pagina ASP.NET che accetta uno s CategoryName
e CategoryID
valori di categoria e restituisce la CategoryName
concatenazione con il numero di prodotti nella categoria (come determinato chiamando il GetCategoriesByProductID(categoryID)
metodo). I risultati di tale funzione di formattazione potrebbero essere assegnati in modo dichiarativo alla proprietà Text di LinkButton sostituendo la necessità del ItemDataBound
gestore eventi. Per altre informazioni sull'uso di funzioni di formattazione, fare riferimento a Using TemplateFields in GridView Control o Formatting the DataList and Repeater Based On Data Tutorials (Uso di templateFields in GridView Control o Formattazione di DataList e Ripetitore basato su dati).
Dopo aver aggiunto questo gestore eventi, eseguire un momento per testare la pagina tramite un browser. Si noti come ogni categoria è elencata in un elenco puntato, visualizzando il nome della categoria e il numero di prodotti associati alla categoria (vedere la figura 4).
Figura 4: Vengono visualizzati il nome e il numero di prodotti di ogni categoria (fare clic per visualizzare l'immagine full-size)
Aggiornamento diCategoriesDataTable
eCategoriesTableAdapter
per includere il numero di prodotti per ogni categoria
Anziché determinare il numero di prodotti per ogni categoria come associato al ripetitore, è possibile semplificare questo processo modificando e CategoriesDataTable
CategoriesTableAdapter
nel livello di accesso ai dati per includere queste informazioni in modo nativo. A questo scopo, è necessario aggiungere una nuova colonna per CategoriesDataTable
contenere il numero di prodotti associati. Per aggiungere una nuova colonna a una tabella dati, aprire Typed DataSet (App_Code\DAL\Northwind.xsd
), fare clic con il pulsante destro del mouse su DataTable per modificare e scegliere Aggiungi/Colonna. Aggiungere una nuova colonna all'oggetto CategoriesDataTable
(vedere la figura 5).
Figura 5: Aggiungere una nuova colonna all'oggetto CategoriesDataSource
(Fare clic per visualizzare l'immagine full-size)
Verrà aggiunta una nuova colonna denominata Column1
, che è possibile modificare digitando semplicemente un nome diverso. Rinominare questa nuova colonna in NumberOfProducts
. Successivamente, è necessario configurare le proprietà di questa colonna. Fare clic sulla nuova colonna e passare alla Finestra Proprietà. Modificare la proprietà della DataType
colonna da System.String
a System.Int32
e impostare la ReadOnly
proprietà su True
, come illustrato nella figura 6.
Figura 6: Impostare le DataType
proprietà e ReadOnly
della nuova colonna
Anche se ora CategoriesDataTable
include una NumberOfProducts
colonna, il relativo valore non viene impostato da alcuna query tableAdapter corrispondente. È possibile aggiornare il GetCategories()
metodo per restituire queste informazioni se si desidera che tali informazioni vengano restituite ogni volta che vengono recuperate le informazioni sulle categorie. Se, tuttavia, è sufficiente acquisire il numero di prodotti associati per le categorie in rari casi (ad esempio solo per questa esercitazione), è possibile lasciare GetCategories()
così com'è e creare un nuovo metodo che restituisce queste informazioni. Usare questo secondo approccio, creando un nuovo metodo denominato GetCategoriesAndNumberOfProducts()
.
Per aggiungere questo nuovo GetCategoriesAndNumberOfProducts()
metodo, fare clic con il pulsante destro del CategoriesTableAdapter
mouse su e scegliere Nuova query. Verrà visualizzata la Configurazione guidata query TableAdapter, che è stata usata numerose volte nelle esercitazioni precedenti. Per questo metodo, avviare la procedura guidata indicando che la query usa un'istruzione SQL ad hoc che restituisce righe.
Figura 7: Creare il metodo usando un'istruzione SQL ad hoc (fare clic per visualizzare l'immagine a dimensione intera)
Figura 8: L'istruzione SQL restituisce righe (fare clic per visualizzare l'immagine a dimensione intera)
La schermata successiva della procedura guidata richiede l'uso della query. Per restituire i campi , e di CategoryID
ogni categoria, insieme al numero di prodotti associati alla categoria, usare l'istruzione seguenteSELECT
:Description
CategoryName
SELECT CategoryID, CategoryName, Description,
(SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
as NumberOfProducts
FROM Categories c
Figura 9: Specificare la query da usare (fare clic per visualizzare l'immagine a dimensione intera)
Si noti che la sottoquery che calcola il numero di prodotti associati alla categoria viene aliasata come NumberOfProducts
. Questa corrispondenza di denominazione fa sì che il valore restituito da questa sottoquery sia associato CategoriesDataTable
alla colonna s NumberOfProducts
.
Dopo aver immesso questa query, l'ultimo passaggio consiste nel scegliere il nome del nuovo metodo. Usare FillWithNumberOfProducts
e GetCategoriesAndNumberOfProducts
per compilare una tabella DataTable e restituire rispettivamente un modello DataTable.
Figura 10: Denominare i nuovi metodi FillWithNumberOfProducts
tableAdapter e GetCategoriesAndNumberOfProducts
(fare clic per visualizzare l'immagine a dimensione intera)
A questo punto il livello di accesso ai dati è stato esteso per includere il numero di prodotti per categoria. Poiché tutti i livelli di presentazione instradano tutte le chiamate a DAL tramite un livello di logica di business separato, è necessario aggiungere un metodo corrispondente GetCategoriesAndNumberOfProducts
alla CategoriesBLL
classe :
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetCategoriesAndNumberOfProducts() As Northwind.CategoriesDataTable
Return Adapter.GetCategoriesAndNumberOfProducts()
End Function
Dopo aver completato DAL e BLL, siamo pronti per associare questi dati al Categories
Repeater in CategoriesAndProducts.aspx
! Se è già stato creato un oggetto ObjectDataSource per Repeater dalla sezione Determinazione del numero di prodotti nella ItemDataBound
sezione Gestore eventi, eliminare questa proprietà ObjectDataSource e rimuovere l'impostazione della DataSourceID
proprietà Repeater; rimuovere anche l'evento Repeater dal ItemDataBound
gestore eventi rimuovendo la Handles Categories.OnItemDataBound
sintassi nella classe code-behind ASP.NET.
Con repeater nuovamente nello stato originale, aggiungere un nuovo ObjectDataSource denominato CategoriesDataSource
tramite lo smart tag repeater. Configurare ObjectDataSource per l'uso della CategoriesBLL
classe , ma anziché usare il GetCategories()
metodo , usare GetCategoriesAndNumberOfProducts()
invece (vedere la figura 11).
Figura 11: Configurare ObjectDataSource per l'uso del metodo (fare clic per visualizzare l'immagineGetCategoriesAndNumberOfProducts
a dimensione intera)
Aggiornare quindi in ItemTemplate
modo che la proprietà LinkButton venga Text
assegnata in modo dichiarativo usando la sintassi databinding e includa sia i CategoryName
NumberOfProducts
campi dati che . Il markup dichiarativo completo per Repeater e CategoriesDataSource
ObjectDataSource segue:
<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:LinkButton runat="server" ID="ViewCategory"
Text='<%# String.Format("{0} ({1:N0})", _
Eval("CategoryName"), Eval("NumberOfProducts")) %>' />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategoriesAndNumberOfProducts" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
L'output di cui è stato eseguito il rendering aggiornando DAL per includere una NumberOfProducts
colonna equivale all'uso dell'approccio ItemDataBound
del gestore eventi (fare riferimento alla figura 4 per visualizzare una schermata del ripetitore che mostra i nomi di categoria e il numero di prodotti).
Passaggio 3: Visualizzazione dei prodotti della categoria selezionata
A questo punto, Categories
il ripetitore visualizza l'elenco delle categorie insieme al numero di prodotti in ogni categoria. Repeater usa un linkbutton per ogni categoria che, quando si fa clic, provoca un postback, a questo punto è necessario visualizzare tali prodotti per la categoria selezionata in CategoryProducts
DataList.
Una sfida per noi è come fare in modo che DataList visualizzi solo i prodotti per la categoria selezionata. In Master/Detail Using a Selectable Master GridView with a Details DetailsView tutorial we saw how to build a GridView the rows could be selected, with the selected row s details being display in a DetailsView on the same page. GridView s ObjectDataSource ha restituito informazioni su tutti i prodotti utilizzando il ProductsBLL
metodo s GetProducts()
mentre DetailsView s ObjectDataSource ha recuperato informazioni sul prodotto selezionato utilizzando il GetProductsByProductID(productID)
metodo . Il valore del productID
parametro è stato fornito in modo dichiarativo associandolo al valore della proprietà gridView.SelectedValue
Sfortunatamente, repeater non dispone di una SelectedValue
proprietà e non può fungere da origine di parametri.
Nota
Questo è uno di questi problemi che vengono visualizzati quando si usa LinkButton in un repeater. Se invece è stato usato un collegamento ipertestuale per passare tramite CategoryID
la stringa di query, è possibile usare il campo QueryString come origine per il valore del parametro.
Prima di preoccuparsi della mancanza di una SelectedValue
proprietà per Repeater, tuttavia, è prima possibile associare DataList a objectDataSource e specificarne ItemTemplate
.
Dallo smart tag di DataList scegliere di aggiungere un nuovo ObjectDataSource denominato CategoryProductsDataSource
e configurarlo per l'uso del ProductsBLL
metodo della GetProductsByCategoryID(categoryID)
classe. Poiché DataList in questa esercitazione offre un'interfaccia di sola lettura, è possibile impostare gli elenchi a discesa nelle schede INSERT, UPDATE e DELETE su (Nessuno).
Figura 12: Configurare ObjectDataSource per l'uso ProductsBLL
del metodo della GetProductsByCategoryID(categoryID)
classe (fare clic per visualizzare l'immagine a dimensione intera)
Poiché il GetProductsByCategoryID(categoryID)
metodo prevede un parametro di input (categoryID
), la procedura guidata Configura origine dati consente di specificare l'origine del parametro. Se le categorie sono state elencate in un controllo GridView o in un oggetto DataList, l'elenco a discesa Origine parametri è stato impostato su Control e controlID sul ID
controllo Web dei dati. Tuttavia, poiché repeater non dispone di una SelectedValue
proprietà, non può essere usata come origine di parametri. Se si seleziona, l'elenco a discesa ControlID contiene un solo controllo ID``CategoryProducts
, dell'oggetto ID
DataList.
Per il momento, impostare l'elenco a discesa Origine parametri su Nessuno. Questo valore di parametro verrà assegnato a livello di codice quando si fa clic su una categoria LinkButton nel ripetitore.
Figura 13: Non specificare un'origine parametro per il categoryID
parametro (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver completato la procedura guidata Configura origine dati, Visual Studio genera automaticamente l'oggetto DataList s ItemTemplate
. Sostituire questa impostazione predefinita ItemTemplate
con il modello usato nell'esercitazione precedente. Impostare anche la proprietà DataList s RepeatColumns
su 2. Dopo aver apportato queste modifiche, il markup dichiarativo per DataList e l'oggetto ObjectDataSource associato dovrebbero essere simili ai seguenti:
<asp:DataList ID="CategoryProducts" runat="server" DataKeyField="ProductID"
DataSourceID="CategoryProductsDataSource" RepeatColumns="2"
EnableViewState="False">
<ItemTemplate>
<h5><%# Eval("ProductName") %></h5>
<p>
Supplied by <%# Eval("SupplierName") %><br />
<%# Eval("UnitPrice", "{0:C}") %>
</p>
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="CategoryProductsDataSource"
OldValuesParameterFormatString="original_{0}" runat="server"
SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
<SelectParameters>
<asp:Parameter Name="categoryID" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
Attualmente, il CategoryProductsDataSource
parametro objectDataSource s categoryID
non viene mai impostato, quindi non viene visualizzato alcun prodotto durante la visualizzazione della pagina. È necessario impostare questo valore di parametro in base all'oggetto CategoryID
della categoria selezionata nel Repeater. Ciò introduce due sfide: in primo luogo, come determinare quando è stato fatto clic su un linkbutton nel ripetitore; ItemTemplate
e in secondo luogo, come è possibile determinare l'oggetto CategoryID
della categoria corrispondente su cui è stato fatto clic su LinkButton?
Il pulsante LinkButton come i controlli Button e ImageButton ha un Click
evento e un Command
evento. L'evento Click
è progettato per notare semplicemente che è stato fatto clic su LinkButton. A volte, tuttavia, oltre a notare che è stato fatto clic su LinkButton, è necessario passare anche alcune informazioni aggiuntive al gestore eventi. In questo caso, alle proprietà e CommandArgument
alle proprietà LinkButton CommandName
è possibile assegnare queste informazioni aggiuntive. Quindi, quando si fa clic su LinkButton, il relativo Command
evento viene generato (anziché il relativo Click
evento) e il gestore eventi viene passato ai valori delle CommandName
proprietà e CommandArgument
.
Quando un Command
evento viene generato dall'interno di un modello nel Repeater, l'evento Repeater viene ItemCommand
generato e viene passato i CommandName
valori e CommandArgument
del pulsante o Button o ImageButton selezionato. Pertanto, per determinare quando è stato fatto clic su un linkbutton di categoria nel ripetitore, è necessario eseguire le operazioni seguenti:
- Impostare la
CommandName
proprietà di LinkButton in Repeater sItemTemplate
su un valore (ho usato ListProducts). Impostando questoCommandName
valore, l'evento LinkButton vieneCommand
generato quando si fa clic su LinkButton. - Impostare la proprietà LinkButton sul
CommandArgument
valore dell'elemento corrente.CategoryID
- Creare un gestore eventi per l'evento Repeater.
ItemCommand
Nel gestore eventi impostare ilCategoryProductsDataSource
parametro ObjectDataSource sulCategoryID
valore dell'oggetto passato.CommandArgument
Il markup seguente ItemTemplate
per Il ripetitore categorie implementa i passaggi 1 e 2. Si noti che al valore viene assegnato l'elemento CommandArgument
CategoryID
di dati usando la sintassi databinding:
<ItemTemplate>
<li>
<asp:LinkButton CommandName="ListProducts" runat="server"
CommandArgument='<%# Eval("CategoryID") %>' ID="ViewCategory"
Text='<%# string.Format("{0} ({1:N0})", _
Eval("CategoryName"), Eval("NumberOfProducts")) %>'>
</asp:LinkButton>
</li>
</ItemTemplate>
Ogni volta che si crea un ItemCommand
gestore eventi, è consigliabile controllare sempre il valore in ingresso CommandName
perché qualsiasiCommand
evento generato da qualsiasi evento Button, LinkButton o ImageButton all'interno del Repeater causerà l'attivazione dell'evento ItemCommand
. Anche se attualmente è disponibile un solo linkButton, in futuro microsoft (o un altro sviluppatore del team) potrebbe aggiungere altri controlli Web pulsante al Repeater che, quando si fa clic, genera lo stesso ItemCommand
gestore eventi. Pertanto, è consigliabile assicurarsi sempre di controllare la proprietà e procedere solo con la CommandName
logica programmatica se corrisponde al valore previsto.
Dopo aver verificato che il valore passato CommandName
sia uguale a ListProducts, il gestore eventi assegna quindi il CategoryProductsDataSource
parametro ObjectDataSource al CategoryID
valore dell'oggetto passato.CommandArgument
Questa modifica apportata a ObjectDataSource fa SelectParameters
sì che DataList venga riassociato automaticamente all'origine dati, mostrando i prodotti per la categoria appena selezionata.
Protected Sub Categories_ItemCommand(source As Object, e As RepeaterCommandEventArgs) _
Handles Categories.ItemCommand
' If it's the "ListProducts" command that has been issued...
If String.Compare(e.CommandName, "ListProducts", True) = 0 Then
' Set the CategoryProductsDataSource ObjectDataSource's CategoryID parameter
' to the CategoryID of the category that was just clicked (e.CommandArgument)...
CategoryProductsDataSource.SelectParameters("CategoryID").DefaultValue = _
e.CommandArgument.ToString()
End If
End Sub
Con queste aggiunte, il nostro tutorial è completo! Provarlo in un browser. Nella figura 14 viene visualizzata la schermata quando si visita per la prima volta la pagina. Poiché una categoria non è ancora selezionata, non vengono visualizzati prodotti. Facendo clic su una categoria, ad esempio Produce, tali prodotti vengono visualizzati nella categoria Product in una visualizzazione a due colonne (vedere la figura 15).
Figura 14: Nessun prodotto viene visualizzato quando si visita per la prima volta la pagina (fare clic per visualizzare l'immagine a dimensione intera)
Figura 15: Fare clic sulla categoria Produce Elenchi i prodotti corrispondenti a destra (fare clic per visualizzare l'immagine a dimensione intera)
Riepilogo
Come illustrato in questa esercitazione e in quella precedente, i report master/dettagli possono essere distribuiti in due pagine o consolidati su uno. La visualizzazione di un report master/dettagli in una singola pagina presenta tuttavia alcune problematiche relative al modo migliore per il layout dei record master e dettagli nella pagina. In Master/Detail Using a Selectable Master GridView with a Details DetailsView tutorial we had the details records appear above the master records; in questa esercitazione sono state usate tecniche CSS per fare in modo che i record master siano float a sinistra dei dettagli.
Oltre alla visualizzazione di report master/dettagli, è stata anche possibile esplorare come recuperare il numero di prodotti associati a ogni categoria e come eseguire la logica lato server quando viene fatto clic su LinkButton (o Button o ImageButton) all'interno di un ripetitore.
Questa esercitazione completa l'esame dei report master/dettagli con DataList e Repeater. Il set successivo di esercitazioni illustra come aggiungere modifiche ed eliminare funzionalità al controllo DataList.
Programmazione felice!
Altre informazioni
Per altre informazioni sugli argomenti illustrati in questa esercitazione, vedere le risorse seguenti:
- Floatutorial un'esercitazione sugli elementi CSS mobili con CSS
- Posizionamento CSS per altre informazioni sull'inserimento di elementi con CSS
- Disposizione del contenuto con HTML usando
<table>
s e altri elementi HTML per la posizione
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Microsoft Web dal 1998. Scott lavora come consulente indipendente, allenatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2,0 in 24 Ore. Può essere raggiunto a mitchell@4GuysFromRolla.com. o tramite il suo blog, che può essere trovato in http://ScottOnWriting.NET.
Grazie speciali
Questa serie di esercitazioni è stata esaminata da molti revisori utili. Il revisore principale per questa esercitazione era Zack Jones. Interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami 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