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 illustra come aggiungere una colonna di pulsanti di opzione a un controllo GridView per fornire all'utente un modo più intuitivo per selezionare una singola riga di GridView.
Introduzione
Il controllo GridView offre una grande quantità di funzionalità predefinite. Include diversi campi per la visualizzazione di testo, immagini, collegamenti ipertestuali e pulsanti. Supporta modelli per un'ulteriore personalizzazione. Con pochi clic del mouse, è possibile creare un controllo GridView in cui ogni riga può essere selezionata tramite un pulsante o per abilitare la modifica o l'eliminazione di funzionalità. Nonostante la pletora di funzionalità fornite, spesso ci saranno situazioni in cui sarà necessario aggiungere funzionalità aggiuntive non supportate. In questa esercitazione e i due successivi si esaminerà come migliorare la funzionalità di GridView per includere funzionalità aggiuntive.
Questa esercitazione e quella successiva si concentrano sul miglioramento del processo di selezione delle righe. Come esaminato nel Master/Detail usando un controllo GridView Master selezionabile con un Details DetailView, è possibile aggiungere un CommandField al GridView che include il pulsante Seleziona. Quando si fa clic, viene eseguito un postback e la proprietà gridView s SelectedIndex
viene aggiornata all'indice della riga su cui è stato fatto clic sul pulsante Seleziona. Nell'esercitazione Master/Detail Using a Selectable Master GridView with a Details DetailView, abbiamo visto come utilizzare questa funzionalità per visualizzare i dettagli della riga selezionata nella GridView.
Anche se il pulsante Seleziona funziona in molte situazioni, potrebbe non funzionare anche per altri utenti. Invece di usare un pulsante, vengono comunemente usati due altri elementi dell'interfaccia utente per la selezione: il pulsante di opzione e la casella di controllo. È possibile aumentare GridView in modo che invece di un pulsante Seleziona ogni riga contenga un pulsante di opzione o una casella di controllo. Negli scenari in cui l'utente può selezionare solo uno dei record nella vista griglia, il pulsante di opzione (radio button) potrebbe essere preferibile rispetto al pulsante Seleziona. In situazioni in cui l'utente può potenzialmente selezionare più record, ad esempio in un'applicazione di posta elettronica basata sul Web, in cui un utente potrebbe voler selezionare più messaggi per eliminare la casella di controllo offre funzionalità non disponibili dal pulsante Seleziona o dalle interfacce utente del pulsante di opzione.
Questa esercitazione illustra come aggiungere una colonna di pulsanti di opzione a GridView. L'esercitazione in corso illustra l'uso delle caselle di controllo.
Passaggio 1: Creare le pagine Web di GridView migliorate
Prima di iniziare a migliorare GridView per includere una colonna di pulsanti di opzione, è necessario prima di tutto creare le pagine ASP.NET nel progetto del sito Web che saranno necessarie per questa esercitazione e le due successive. Per iniziare, aggiungere una nuova cartella denominata EnhancedGridView
. Aggiungere quindi le pagine di ASP.NET seguenti a tale cartella, assicurandosi di associare ogni pagina alla Site.master
pagina master:
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
Figura 1: Aggiungere le pagine ASP.NET per le esercitazioni SqlDataSource-Related
Come nelle altre cartelle, Default.aspx
nella cartella EnhancedGridView
elenca le esercitazioni nella relativa sezione. Tenere presente che il SectionLevelTutorialListing.ascx
controllo utente fornisce questa funzionalità. Aggiungere quindi questo controllo utente a Default.aspx
trascinandolo da Esplora soluzioni nella visualizzazione di progettazione della pagina.
Figura 2: Aggiungere il SectionLevelTutorialListing.ascx
controllo utente a Default.aspx
(fare clic per visualizzare l'immagine a dimensione intera)
Infine, aggiungi queste quattro pagine come voci nel file Web.sitemap
. In particolare, aggiungere il markup seguente dopo l'uso del controllo <siteMapNode>
SqlDataSource :
<siteMapNode
title="Enhancing the GridView"
url="~/EnhancedGridView/Default.aspx"
description="Augment the user experience of the GridView control.">
<siteMapNode
url="~/EnhancedGridView/RadioButtonField.aspx"
title="Selection via a Radio Button Column"
description="Explore how to add a column of radio buttons in the GridView." />
<siteMapNode
url="~/EnhancedGridView/CheckBoxField.aspx"
title="Selection via a Checkbox Column"
description="Select multiple records in the GridView by using a column of
checkboxes." />
<siteMapNode
url="~/EnhancedGridView/InsertThroughFooter.aspx"
title="Add New Records through the Footer"
description="Learn how to allow users to add new records through the
GridView's footer." />
</siteMapNode>
Dopo l'aggiornamento Web.sitemap
, dedica qualche minuto per visitare il sito web delle esercitazioni tramite un browser. Il menu a sinistra include ora elementi per le esercitazioni di modifica, inserimento ed eliminazione.
Figura 3: La mappa del sito include ora le voci per il miglioramento delle esercitazioni su GridView
Passaggio 2: Visualizzazione dei fornitori in un elemento GridView
Per questa esercitazione, costruiamo un GridView che elenca i fornitori dagli Stati Uniti, con ogni riga del GridView che presenta un pulsante di opzione. Dopo aver selezionato un fornitore tramite il pulsante di opzione, l'utente può visualizzare i prodotti del fornitore facendo clic su un pulsante. Anche se questo compito può sembrare semplice, ci sono una serie di sottigliezze che lo rendono particolarmente difficile. Prima di approfondire queste sottigliezze, è possibile ottenere un gridView che elenca i fornitori.
Per iniziare, aprire la RadioButtonField.aspx
pagina nella EnhancedGridView
cartella trascinando GridView dal Toolbox sul Designer. Impostare GridView s ID
su Suppliers
e, dallo smart tag, scegliere di creare una nuova origine dati. In particolare, creare un ObjectDataSource denominato SuppliersDataSource
che estrae i dati dall'oggetto SuppliersBLL
.
Creare un nuovo ObjectDataSource denominato SuppliersDataSource
Figura 4: Creare un nuovo oggettoDataSource denominato SuppliersDataSource
(fare clic per visualizzare l'immagine a dimensione intera)
Figura 5: Configurare ObjectDataSource per l'uso della classe (SuppliersBLL
a dimensione intera)
Poiché si vogliono elencare solo i fornitori negli Stati Uniti, scegliere il GetSuppliersByCountry(country)
metodo dall'elenco a discesa nella scheda SELECT.
Figura 6: Configurare ObjectDataSource per l'uso della classe (SuppliersBLL
a dimensione intera)
Nella scheda UPDATE selezionare l'opzione (Nessuno) e fare clic su Avanti.
Figura 7: Configurare ObjectDataSource per l'uso della classe (SuppliersBLL
a dimensione intera)
Poiché il GetSuppliersByCountry(country)
metodo accetta un parametro, la procedura guidata Configura origine dati richiede l'origine di tale parametro. Per specificare un valore codificato (USA, in questo esempio), lasciare l'elenco a discesa Origine parametro impostato su Nessuno e immettere il valore di default nella casella di testo. Fare clic su Fine per completare la procedura guidata.
Figura 8: Usare USA come valore predefinito per il parametro (country
a dimensione intera)
Al termine della procedura guidata, GridView includerà un BoundField per ognuno dei campi dati del fornitore. Rimuovere tutto tranne i CompanyName
, City
e Country
BoundFields e rinominare la proprietà del BoundField CompanyName
in Supplier. Dopo questa operazione, la sintassi dichiarativa GridView e ObjectDataSource dovrebbe essere simile alla seguente.
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
<SelectParameters>
<asp:Parameter DefaultValue="USA" Name="country" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
Per questa esercitazione, consentire all'utente di visualizzare i prodotti del fornitore selezionato nella stessa pagina dell'elenco dei fornitori o in una pagina diversa. Per soddisfare questa esigenza, aggiungere due controlli Web di tipo pulsante alla pagina. Ho impostato i ID
di questi due pulsanti su ListProducts
e SendToProducts
, con l'idea che quando si fa clic su ListProducts
, si verificherà un postback e i prodotti del fornitore selezionato verranno elencati nella stessa pagina, mentre quando si fa clic su SendToProducts
, l'utente verrà portato su un'altra pagina in cui sono elencati i prodotti.
La figura 9 mostra i Suppliers
controlli GridView e i due controlli Web Button quando vengono visualizzati tramite un browser.
Figura 9: I fornitori degli Stati Uniti hanno il nome, la città e le informazioni sul paese elencate (fare clic per visualizzare l'immagine a dimensione intera)
Passaggio 3: Aggiunta di una colonna di pulsanti di opzione
A questo punto, Suppliers
GridView ha tre BoundFields che visualizzano il nome della società, la città e il paese di ogni fornitore negli Stati Uniti. Tuttavia, manca ancora una colonna di pulsanti di opzione. Purtroppo, la GridView non include un RadioButtonField predefinito, altrimenti potremmo semplicemente aggiungerlo alla griglia e aver finito. Invece, possiamo aggiungere un TemplateField e configurare il suo ItemTemplate
per mostrare un pulsante di opzione, generando un pulsante di opzione per ogni riga del GridView.
Inizialmente, si potrebbe presupporre che l'interfaccia utente desiderata possa essere implementata aggiungendo un controllo Web RadioButton a ItemTemplate
di un oggetto TemplateField. Anche se questo aggiungerà effettivamente un singolo pulsante di opzione a ogni riga di GridView, i pulsanti di opzione non possono essere raggruppati e pertanto non si escludono a vicenda. Ovvero, un utente finale è in grado di selezionare più pulsanti di opzione contemporaneamente da GridView.
Anche se l'uso di un TemplateField con controlli Web RadioButton non offre le funzionalità necessarie, implementiamo comunque questo approccio, poiché è utile esaminare perché i pulsanti di opzione risultanti non sono raggruppati. Per iniziare, aggiungere un oggetto TemplateField a Suppliers GridView, rendendolo il campo più a sinistra. Successivamente, dallo smart tag GridView, fare clic sul collegamento Modifica modelli e trascinare un controllo Web RadioButton dalla casella degli strumenti nel ItemTemplate
di TemplateField (vedere la figura 10). Impostare la proprietà RadioButton su ID
RowSelector
e la GroupName
proprietà su SuppliersGroup
.
Figura 10: Aggiungere un controllo Web RadioButton a ItemTemplate
(fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver apportato queste aggiunte tramite la finestra di progettazione, il markup di GridView dovrebbe essere simile al seguente:
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:RadioButton ID="RowSelector" runat="server"
GroupName="SuppliersGroup" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
La proprietà RadioButton GroupName
viene utilizzata per raggruppare una serie di pulsanti di opzione. Tutti i controlli RadioButton con lo stesso GroupName
valore vengono considerati raggruppati. È possibile selezionare un solo pulsante di opzione da un gruppo alla volta. La proprietà GroupName
specifica il valore dell'attributo name
del pulsante di opzione renderizzato. Il browser esamina gli attributi name
dei pulsanti radio per determinare i raggruppamenti dei pulsanti radio.
Con il controllo Web RadioButton aggiunto a ItemTemplate
, visitare questa pagina tramite un browser e fare clic sui pulsanti di opzione nelle righe della griglia. Si noti che i pulsanti di opzione non sono raggruppati, rendendo possibile selezionare tutte le righe, come illustrato nella Figura 11.
Figura 11: I pulsanti di opzione di GridView non sono raggruppati (fare clic per visualizzare l'immagine a dimensione intera)
Il motivo per cui i pulsanti di opzione non sono raggruppati è che gli attributi name
sottoposti a rendering sono diversi, nonostante abbiano la stessa impostazione della proprietà GroupName
. Per visualizzare queste differenze, utilizzare la funzione Visualizza sorgente nel browser ed esaminare il markup del pulsante di scelta.
<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector"
name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector"
name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector"
name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector"
name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup"
type="radio" value="RowSelector" />
Si noti che gli name
attributi e id
non sono i valori esatti specificati nella finestra Proprietà, ma vengono anteporti a un numero di altri ID
valori. I valori aggiuntivi ID
aggiunti nella parte anteriore degli attributi renderizzati id
e name
sono i controlli genitori ID
dei pulsanti radio GridViewRow
ID
, il GridView ID
, il controllo Contenuto ID
e il Web Form ID
. Questi ID
vengono aggiunti affinché ogni controllo Web reso nel GridView abbia valori id
e name
univoci.
Ogni controllo di cui è stato eseguito il rendering richiede un diverso name
e id
perché questo è il modo in cui il browser identifica in modo univoco ogni controllo sul lato client e il modo in cui comunica al server web quale azione o modifica è avvenuta durante il postback. Si supponga, ad esempio, di voler eseguire codice lato server ogni volta che viene modificato lo stato di selezione di un RadioButton. Possiamo ottenere questo impostando la proprietà di RadioButton su AutoPostBack
true
e creando un gestore eventi per l'evento CheckChanged
. Tuttavia, se i valori resi di name
e id
per tutti i pulsanti di opzione fossero gli stessi, al momento del postback non sarebbe possibile determinare quale pulsante radio specifico è stato cliccato.
In sintesi, non è possibile creare una colonna di bottoni di opzione in un controllo GridView utilizzando il controllo Web RadioButton. È invece necessario usare tecniche piuttosto arcaiche per assicurarsi che il markup appropriato venga inserito in ogni riga gridView.
Annotazioni
Come il controllo Web RadioButton, il controllo HTML del pulsante di opzione, quando viene aggiunto a un modello, includerà l'attributo univoco name
, rendendo i pulsanti di opzione nella griglia non raggruppati. Se non si ha familiarità con i controlli HTML, è possibile ignorare questa nota, poiché i controlli HTML vengono usati raramente, soprattutto in ASP.NET 2.0. Tuttavia, se si è interessati a saperne di più, vedere K. Scott Allen blog entry Web Controls and HTML Controls (Controlli Web e controlli HTML).
Uso di un controllo Literal per inserire il markup del pulsante radio
Per raggruppare correttamente tutti i pulsanti di opzione all'interno di GridView, è necessario inserire manualmente il markup dei pulsanti di opzione in ItemTemplate
. Ogni pulsante di opzione richiede lo stesso name
attributo, ma deve avere un attributo univoco id
(nel caso in cui si voglia accedere a un pulsante di opzione tramite script sul lato client). Dopo che un utente seleziona un pulsante di scelta e pubblica la pagina, il browser invierà di nuovo il valore dell'attributo del pulsante di scelta selezionatovalue
. Di conseguenza, ogni pulsante di opzione richiederà un attributo univoco value
. Infine, al postback, è necessario assicurarsi di aggiungere l'attributo checked
all'unico pulsante di opzione che è stato selezionato, altrimenti, dopo che l'utente ha effettuato una selezione e ha effettuato il postback, i pulsanti di opzione torneranno al loro stato predefinito (tutti i pulsanti non selezionati).
Esistono due approcci che è possibile adottare per inserire markup di basso livello in un modello. Uno consiste nell'eseguire una combinazione di markup e chiamate ai metodi di formattazione definiti nella classe code-behind. Questa tecnica è stata discussa per la prima volta nel tutorial Uso di TemplateFields nel controllo GridView. In questo caso potrebbe essere simile al seguente:
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
Qui, GetUniqueRadioButton
e GetRadioButtonValue
sarebbero metodi definiti nella classe code-behind che restituiscono i valori appropriati dell'attributo id
e value
per ciascun pulsante di opzione. Questo approccio funziona bene per l'assegnazione degli attributi id
e value
, ma presenta delle limitazioni quando si tratta di specificare il valore dell'attributo checked
perché la sintassi di associazione dati viene eseguita solo quando i dati vengono associati per la prima volta al GridView. Pertanto, se gridView ha lo stato di visualizzazione abilitato, i metodi di formattazione verranno attivati solo quando la pagina viene caricata per la prima volta (o quando GridView viene riassegnata in modo esplicito all'origine dati) e pertanto la funzione che imposta l'attributo checked
non verrà chiamata al postback. Si tratta di un problema piuttosto sottile e un po ' oltre l'ambito di questo articolo, quindi lo lascerò a questo. Tuttavia, ti incoraggio a provare a usare l'approccio precedente e a seguirlo fino al punto in cui ti blocchi. Anche se un esercizio di questo tipo non ti avvicina a una versione funzionante, contribuirà a promuovere una comprensione più approfondita del ciclo di vita di GridView e del databinding.
L'altro approccio all'inserimento di markup personalizzati di basso livello in un modello e all'approccio che verrà usato per questa esercitazione consiste nell'aggiungere un controllo Literal al modello. Quindi, nel gestore eventi GridViewRowCreated
o RowDataBound
, il controllo Literal può essere accesso programmaticamente e la proprietà Text
impostata sul markup da generare.
Inizia rimuovendo il controllo RadioButton da TemplateField ItemTemplate
, sostituendolo con un controllo Literal. Impostare il controllo Literal s ID
su RadioButtonMarkup
.
Figura 12: Aggiungere un controllo letterale al ItemTemplate
(fare clic qui per visualizzare l'immagine a dimensione intera)
Creare quindi un gestore eventi per l'evento GridView.RowCreated
L'evento RowCreated
viene generato una volta per ogni riga aggiunta, indipendentemente dal fatto che i dati vengano reinterpretati in GridView. Questo significa che anche in un postback, quando i dati vengono ricaricati dallo stato di visualizzazione, l'evento RowCreated
è ancora attivato e questo è il motivo per cui viene utilizzato al posto di RowDataBound
(che viene generato solo quando i dati sono associati esplicitamente al controllo Web dati).
In questo gestore eventi si vuole procedere solo se si tratta di una riga di dati. Vogliamo fare riferimento programmaticamente al controllo RadioButtonMarkup
Literal per ogni riga di dati e impostarne la proprietà Text
sul markup da generare. Come mostrato nel codice seguente, il markup generato crea un radio button il cui attributo name
è impostato su SuppliersGroup
, il cui attributo id
è impostato su RowSelectorX
, dove X è l'indice della riga GridView, e il cui attributo value
è impostato sull'indice della riga GridView.
protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Grab a reference to the Literal control
Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
// Output the markup except for the "checked" attribute
output.Text = string.Format(
@"<input type="radio" name="SuppliersGroup" " +
@"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex);
}
}
Quando viene selezionata una riga del GridView e si verifica un postback, ci interessa il SupplierID
del fornitore selezionato. Pertanto, si potrebbe pensare che il valore di ogni pulsante di opzione dovrebbe essere l'effettivo SupplierID
(anziché l'indice della riga GridView). Anche se ciò può funzionare in determinate circostanze, sarebbe un rischio per la sicurezza accettare e elaborare in modo cieco un oggetto SupplierID
. Il nostro GridView, ad esempio, elenca solo i fornitori negli Stati Uniti. Tuttavia, se il SupplierID
è passato direttamente dal pulsante di opzione, cosa impedisce a un utente malizioso di modificare il valore SupplierID
inviato al postback? Usando l'indice di riga come value
, e poi ottenendo il SupplierID
durante il postback dalla raccolta DataKeys
, possiamo assicurarci che l'utente utilizzi solo uno dei valori SupplierID
associati a una delle righe del GridView.
Dopo aver aggiunto questo codice del gestore eventi, provare la pagina in un browser. Prima di tutto, si noti che è possibile selezionare un solo pulsante radio nella griglia alla volta. Tuttavia, quando si seleziona un pulsante di opzione e si fa clic su uno dei pulsanti, si verifica un postback e tutti i pulsanti di opzione ripristinano il proprio stato iniziale (ovvero, al postback, il pulsante di opzione selezionato non è più selezionato). Per risolvere questo problema, è necessario modificare il gestore eventi RowCreated
in modo che ispezioni l'indice del radio button selezionato inviato dal postback e aggiunga l'attributo checked="checked"
al markup output quando l'indice di riga corrisponde.
Quando si verifica un postback, il browser restituisce il name
e il value
del pulsante di opzione selezionato. Il valore può essere recuperato a livello di codice tramite Request.Form["name"]
. La Request.Form
proprietà fornisce un oggetto NameValueCollection
che rappresenta le variabili del modulo. Le variabili del modulo sono i nomi e i valori dei campi modulo nella pagina Web e vengono restituiti dal Web browser ogni volta che viene eseguito un postback. Poiché l'attributo name
dei pulsanti di opzione nel GridView viene reso SuppliersGroup
, quando la pagina Web viene inviata nuovamente al server Web, il browser invierà SuppliersGroup=valueOfSelectedRadioButton
(insieme agli altri campi del modulo). È quindi possibile accedere a queste informazioni dalla Request.Form
proprietà utilizzando : Request.Form["SuppliersGroup"]
.
Poiché dobbiamo determinare l'indice del pulsante di opzione selezionato non solo nel gestore eventi RowCreated
, ma anche nei gestori eventi per i controlli Web Button Click
, aggiungiamo una proprietà SuppliersSelectedIndex
alla classe code-behind che restituisce -1
se nessun pulsante di opzione è stato selezionato e l'indice selezionato se uno dei pulsanti di opzione è stato scelto.
private int SuppliersSelectedIndex
{
get
{
if (string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))
return -1;
else
return Convert.ToInt32(Request.Form["SuppliersGroup"]);
}
}
Con questa proprietà aggiunta, sappiamo di dover inserire il markup checked="checked"
nel gestore dell'evento RowCreated
quando SuppliersSelectedIndex
è uguale a e.Row.RowIndex
. Aggiornare il gestore eventi per includere questa logica:
protected void Suppliers_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Grab a reference to the Literal control
Literal output = (Literal)e.Row.FindControl("RadioButtonMarkup");
// Output the markup except for the "checked" attribute
output.Text = string.Format(
@"<input type="radio" name="SuppliersGroup" " +
@"id="RowSelector{0}" value="{0}"", e.Row.RowIndex);
// See if we need to add the "checked" attribute
if (SuppliersSelectedIndex == e.Row.RowIndex)
output.Text += @" checked="checked"";
// Add the closing tag
output.Text += " />";
}
}
Con questa modifica, il pulsante di opzione selezionato rimane selezionato dopo un postback. Ora che è possibile specificare il pulsante di opzione selezionato, è possibile modificare il comportamento in modo che quando la pagina è stata visitata per la prima volta, è stato selezionato il pulsante di opzione della prima riga di GridView (invece di non avere pulsanti di opzione selezionati per impostazione predefinita, ovvero il comportamento corrente). Per fare in modo che il primo pulsante di opzione sia selezionato per impostazione predefinita, è sufficiente modificare l'istruzione if (SuppliersSelectedIndex == e.Row.RowIndex)
nel modo seguente: if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0))
.
A questo punto, abbiamo aggiunto una colonna di pulsanti di opzione raggruppati a GridView che consente di selezionare e ricordare una singola riga di GridView tra i postback. I nostri passaggi successivi sono la visualizzazione dei prodotti forniti dal fornitore selezionato. Nel passaggio 4 verrà illustrato come reindirizzare l'utente a un'altra pagina, inviando lungo l'oggetto selezionato SupplierID
. Nel passaggio 5 verrà illustrato come visualizzare i prodotti del fornitore selezionato in un controllo GridView nella stessa pagina.
Annotazioni
Invece di usare il TemplateField (che è l'argomento principale di questo lungo passaggio 3), è possibile creare una classe personalizzata DataControlField
che rende l'interfaccia utente e le funzionalità appropriate. La DataControlField
classe è la classe base da cui derivano i campi BoundField, CheckBoxField, TemplateField e altri campi GridView e DetailsView predefiniti. La creazione di una classe personalizzata DataControlField
significa che la colonna dei pulsanti di opzione può essere aggiunta solo usando la sintassi dichiarativa e renderebbe anche più semplice replicare le funzionalità in altre pagine Web e altre applicazioni Web.
Se hai mai creato controlli personalizzati e compilati in ASP.NET, sai che questa operazione richiede una quantità notevole di lavoro preliminare e comporta una serie di sottigliezze e casi particolari che devono essere gestiti con attenzione. Di conseguenza, rinunceremo all'implementazione di una colonna di pulsanti di opzione come classe personalizzata DataControlField
per ora e ci atteniamo all'opzione TemplateField. Forse si avrà la possibilità di esplorare la creazione, l'uso e la distribuzione di classi personalizzate DataControlField
in un'esercitazione futura.
Passaggio 4: Visualizzazione dei prodotti dei fornitori selezionati in una pagina separata
Dopo che l'utente ha selezionato una riga GridView, è necessario visualizzare i prodotti del fornitore selezionato. In alcune circostanze, potremmo voler visualizzare questi prodotti in una pagina separata, in altri potrebbe essere preferibile farlo nella stessa pagina. Prima di tutto esaminiamo come visualizzare i prodotti in una pagina separata; nel passaggio 5 si esaminerà come aggiungere un controllo GridView a RadioButtonField.aspx
per visualizzare i prodotti del fornitore selezionato.
Attualmente sono disponibili due controlli Web Button nella pagina ListProducts
e SendToProducts
. Quando si fa clic sul SendToProducts
pulsante, si vuole inviare l'utente a ~/Filtering/ProductsForSupplierDetails.aspx
. Questa pagina è stata creata nel tutorial Filtro Master/Dettaglio attraverso due pagine e visualizza i prodotti per il fornitore, il cui SupplierID
viene passato attraverso il campo della querystring denominato SupplierID
.
Per fornire questa funzionalità, creare un gestore eventi per l'evento SendToProducts
Button s Click
. Nel passaggio 3 è stata aggiunta la proprietà SuppliersSelectedIndex
, che restituisce l'indice della riga, il cui pulsante di opzione è selezionato. Il corrispondente SupplierID
può essere recuperato dalla raccolta DataKeys
di GridView e l'utente può quindi essere inviato a ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
usando Response.Redirect("url")
.
protected void SendToProducts_Click(object sender, EventArgs e)
{
// Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
int supplierID =
Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
Response.Redirect(
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID="
+ supplierID);
}
}
Questo codice funziona in modo meraviglioso, purché uno dei pulsanti di opzione sia selezionato da GridView. Se inizialmente GridView non ha pulsanti di opzione selezionati e l'utente fa clic sul pulsante SendToProducts
, SuppliersSelectedIndex
sarà -1
, che causerà un'eccezione perché -1
non è compreso nell'intervallo di indici della raccolta DataKeys
. Questo non è un problema, tuttavia, se si è deciso di aggiornare il gestore eventi RowCreated
come descritto nel passaggio 3, in modo da avere inizialmente selezionato il primo pulsante di opzione nel GridView.
Per accogliere un valore di SuppliersSelectedIndex
, aggiungere alla pagina, sopra il GridView, un controllo Web di tipo Etichetta. Imposta la proprietà ID
a ChooseSupplierMsg
, la proprietà CssClass
a Warning
, le proprietà EnableViewState
e Visible
a false
, e la proprietà Text
a Scegliere un fornitore dalla griglia. La classe Warning
CSS visualizza il testo in un carattere rosso, corsivo, grassetto, grande ed è definito in Styles.css
. Impostando le proprietà EnableViewState
e Visible
su false
, l'etichetta viene renderizzata solo nei postback in cui la proprietà Visible
del controllo è impostata a livello di codice su true
.
Figura 13: Aggiungere un controllo Web Label sopra il GridView (fare clic per visualizzare l'immagine a grandezza naturale)
Successivamente, aumentare il Click
gestore eventi per visualizzare l'etichetta ChooseSupplierMsg
se SuppliersSelectedIndex
è minore di zero e reindirizzare l'utente a ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
in caso contrario.
protected void SendToProducts_Click(object sender, EventArgs e)
{
// make sure one of the radio buttons has been selected
if (SuppliersSelectedIndex < 0)
ChooseSupplierMsg.Visible = true;
else
{
// Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
int supplierID =
Convert.ToInt32(Suppliers.DataKeys[SuppliersSelectedIndex].Value);
Response.Redirect(
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID="
+ supplierID);
}
}
Visitare la pagina in un browser e fare clic sul SendToProducts
pulsante prima di selezionare un fornitore da GridView. Come illustrato nella figura 14, viene visualizzata l'etichetta ChooseSupplierMsg
. Selezionare quindi un fornitore e fare clic sul SendToProducts
pulsante . Verrà visualizzata una pagina che elenca i prodotti forniti dal fornitore selezionato. La figura 15 mostra la ProductsForSupplierDetails.aspx
pagina in cui è stato selezionato il fornitore Bigfoot Breweries.
Figura 14: L'etichetta ChooseSupplierMsg
viene visualizzata se non è selezionato nessun fornitore (fare clic per visualizzare l'immagine a dimensione intera)
Figura 15: I prodotti del fornitore selezionati sono visualizzati in ProductsForSupplierDetails.aspx
(fare clic per visualizzare l'immagine a dimensione intera)
Passaggio 5: Visualizzazione dei prodotti dei fornitori selezionati nella stessa pagina
Nel passaggio 4 è stato illustrato come inviare l'utente a un'altra pagina Web per visualizzare i prodotti del fornitore selezionato. In alternativa, i prodotti dei fornitori selezionati possono essere visualizzati nella stessa pagina. Per illustrare questo esempio, aggiungeremo un altro GridView a RadioButtonField.aspx
per visualizzare i prodotti del fornitore selezionato.
Poiché vogliamo che il GridView dei prodotti venga visualizzato solo dopo che è stato selezionato un fornitore, aggiungere un controllo Web Panel sotto il Suppliers
GridView, impostando la sua proprietà ID
su ProductsBySupplierPanel
e la proprietà Visible
su false
. Aggiungi il testo 'Products for the Selected Supplier' (Prodotti per il fornitore selezionato) all'interno del pannello, seguito da un controllo GridView denominato ProductsBySupplier
. Dallo smart tag di GridView scegliere di associarlo a un nuovo ObjectDataSource denominato ProductsBySupplierDataSource
.
Figura 16: Associare ProductsBySupplier
GridView a un nuovo oggettoDataSource (fare clic per visualizzare l'immagine a dimensione intera)
Configurare quindi ObjectDataSource per l'uso della ProductsBLL
classe . Poiché si vogliono recuperare solo i prodotti forniti dal fornitore selezionato, specificare che ObjectDataSource deve richiamare il GetProductsBySupplierID(supplierID)
metodo per recuperare i dati. Selezionare (Nessuno) negli elenchi a discesa nelle schede UPDATE, INSERT e DELETE.
Figura 17: Configurare ObjectDataSource per l'uso del metodo (GetProductsBySupplierID(supplierID)
a dimensione intera)
Figura 18: Impostare gli elenchi di Drop-Down su (Nessuno) nelle schede UPDATE, INSERT e DELETE (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver configurato le schede SELECT, UPDATE, INSERT e DELETE, fare clic su Avanti. Poiché il GetProductsBySupplierID(supplierID)
metodo si aspetta un parametro di input, la procedura guidata Crea origine dati ci invita a specificare l'origine del valore del parametro.
Qui sono disponibili due opzioni per specificare l'origine del valore del parametro. È possibile utilizzare l'oggetto Parameter predefinito e assegnare a livello di codice il valore della SuppliersSelectedIndex
proprietà alla proprietà Parameter s DefaultValue
nel gestore eventi di Selecting
ObjectDataSource. Fare riferimento all'esercitazione Impostazione dei valori dei parametri di ObjectDataSource a livello di codice per rinfrescare la memoria sull'assegnazione di valori ai parametri dell'ObjectDataSource.
In alternativa, è possibile usare ControlParameter e fare riferimento alla proprietà di GridView (Suppliers
) nella SelectedValue
figura 19. La proprietà SelectedValue
di GridView restituisce il valore DataKey
corrispondente alla proprietà SelectedIndex
. Per consentire il funzionamento di questa opzione, è necessario impostare a livello di codice la proprietà GridView sulla SelectedIndex
riga selezionata quando si fa clic sul ListProducts
pulsante. Come vantaggio aggiuntivo, impostando il SelectedIndex
, il record selezionato assumerà lo stile SelectedRowStyle
definito nel Tema DataWebControls
(uno sfondo giallo).
Figura 19: Usare un ControlParameter per specificare SelectedValue di GridView come origine del parametro (fare clic per visualizzare l'immagine a schermo intero)
Al termine della procedura guidata, Visual Studio aggiungerà automaticamente campi per i campi dati del prodotto. Rimuovi tutti i BoundFields tranne ProductName
, CategoryName
e UnitPrice
, e modifica le proprietà HeaderText
in Product, Category e Price. Configurare BoundField UnitPrice
in modo che il relativo valore sia formattato come valuta. Dopo aver apportato queste modifiche, il markup dichiarativo di Panel, GridView e ObjectDataSource dovrebbe essere simile al seguente:
<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
<h3>
Products for the Selected Supplier</h3>
<p>
<asp:GridView ID="ProductsBySupplier" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
<SelectParameters>
<asp:ControlParameter ControlID="Suppliers" Name="supplierID"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
</p>
</asp:Panel>
Per completare questo esercizio, è necessario impostare la proprietà gridView su SelectedIndex
e la SelectedSuppliersIndex
proprietà Panel s ProductsBySupplierPanel
su Visible
quando si fa clic sul true
pulsante.ListProducts
Per farlo, creare un gestore eventi per l'evento ListProducts
del controllo Web Button Click
e aggiungere il codice seguente:
protected void ListProducts_Click(object sender, EventArgs e)
{
// make sure one of the radio buttons has been selected
if (SuppliersSelectedIndex < 0)
{
ChooseSupplierMsg.Visible = true;
ProductsBySupplierPanel.Visible = false;
}
else
{
// Set the GridView's SelectedIndex
Suppliers.SelectedIndex = SuppliersSelectedIndex;
// Show the ProductsBySupplierPanel panel
ProductsBySupplierPanel.Visible = true;
}
}
Se un fornitore non è stato selezionato da GridView, l'etichetta ChooseSupplierMsg
viene visualizzata e il ProductsBySupplierPanel
pannello nascosto. In caso contrario, se è stato selezionato un fornitore, ProductsBySupplierPanel
viene visualizzato e la proprietà del GridView viene SelectedIndex
aggiornata.
La figura 20 mostra i risultati dopo che il fornitore Bigfoot Breweries è stato selezionato e il pulsante Mostra prodotti nella pagina è stato selezionato.
Figura 20: I prodotti forniti da Bigfoot Breweries sono elencati nella stessa pagina (fare clic per visualizzare l'immagine a dimensione intera)
Riassunto
Come discusso nell'esercitazione Master/Detail Using a Selectable Master GridView with a Details DetailView, i record possono essere selezionati da un controllo GridView usando un campo CommandField la cui ShowSelectButton
proprietà è impostata su true
. CommandField visualizza i suoi pulsanti come normali pulsanti a pressione, collegamenti o immagini. Un'interfaccia utente alternativa per la selezione di righe consiste nel fornire un pulsante di opzione o una casella di controllo in ogni riga gridView. In questa esercitazione è stato esaminato come aggiungere una colonna di pulsanti di opzione.
Sfortunatamente, l'aggiunta di una colonna di pulsanti di opzione non è facile o semplice come ci si potrebbe aspettare. Non esiste alcun oggetto RadioButtonField predefinito che può essere aggiunto al clic di un pulsante e l'uso del controllo Web RadioButton all'interno di un oggetto TemplateField introduce un proprio set di problemi. Alla fine, per fornire tale interfaccia è necessario creare una classe personalizzata DataControlField
o ricorrere all'inserimento del codice HTML appropriato in un oggetto TemplateField durante l'evento RowCreated
.
Dopo aver esaminato come aggiungere una colonna di pulsanti di opzione, concentriamoci su come aggiungere una colonna di caselle di controllo. Con una colonna di caselle di controllo, un utente può selezionare una o più righe gridView e quindi eseguire alcune operazioni su tutte le righe selezionate( ad esempio selezionando un set di messaggi di posta elettronica da un client di posta elettronica basato sul Web e quindi scegliendo di eliminare tutti i messaggi di posta elettronica selezionati). Nell'esercitazione successiva verrà illustrato come aggiungere una colonna di questo tipo.
Buon programmatori!
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato 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 a mitchell@4GuysFromRolla.com.
Grazie speciale a
Questa serie di esercitazioni è stata esaminata da molti revisori competenti. Il revisore principale per questo tutorial è stato David Suru. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, mandami un messaggio a mitchell@4GuysFromRolla.com.