Aggiunta di una colonna GridView di pulsanti di opzione (C#)

di Scott Mitchell

Scarica il PDF

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 i modelli per ulteriori personalizzazioni. Con alcuni clic del mouse, è possibile creare un controllo GridView in cui ogni riga può essere selezionata tramite un pulsante oppure per abilitare la modifica o l'eliminazione di funzionalità. Nonostante la pletora delle funzionalità fornite, spesso ci saranno situazioni in cui devono essere aggiunte funzionalità aggiuntive non supportate. In questa esercitazione e i due successivi verranno esaminati 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/dettaglio usando un Controllo griglia master selezionabile con un oggetto DetailsView, è possibile aggiungere un commandField a GridView che include un pulsante Select. Quando si fa clic su, viene aggiornato un postback e la proprietà GridView s SelectedIndex viene aggiornata all'indice della riga il cui pulsante Select è stato fatto clic. Nell'esercitazione Master/Details Using a Selectable Master GridView con un'esercitazione DetailsView è stato illustrato come usare questa funzionalità per visualizzare i dettagli per la riga GridView selezionata.

Mentre il pulsante Select funziona in molte situazioni, potrebbe non funzionare anche per gli altri. Anziché usare un pulsante, due altri elementi dell'interfaccia utente vengono comunemente usati per la selezione: il pulsante di opzione e la casella di controllo. È possibile aumentare GridView in modo che, anziché un pulsante Select, ogni riga contenga un pulsante di opzione o una casella di controllo. Negli scenari in cui l'utente può selezionare solo uno dei record GridView, il pulsante di opzione potrebbe essere preferito sul pulsante Seleziona. In situazioni in cui l'utente può selezionare potenzialmente 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à che non sono disponibili dall'interfaccia utente seleziona o pulsante di opzione.

Questa esercitazione illustra come aggiungere una colonna di pulsanti di opzione a GridView. L'esercitazione che procede illustra l'uso delle caselle di controllo.

Passaggio 1: Creazione del miglioramento delle pagine Web gridView

Prima di iniziare a migliorare GridView per includere una colonna di pulsanti di opzione, è prima di tutto necessario creare le pagine ASP.NET nel progetto del sito Web che sarà necessario per questa esercitazione e le due successive. Iniziare aggiungendo 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

Aggiungere le pagine ASP.NET per le esercitazioni SqlDataSource-Related

Figura 1: Aggiungere le pagine ASP.NET per le esercitazioni SqlDataSource-Related

Come nelle altre cartelle, Default.aspx nella EnhancedGridView cartella verranno elencate 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 dalla Esplora soluzioni nella visualizzazione Progettazione della pagina.

Aggiungere il controllo utente SectionLevelTutorialListing.ascx a Default.aspx

Figura 2: Aggiungere il controllo utente a Default.aspx (Fare clic per visualizzare l'immagineSectionLevelTutorialListing.ascx full-size)

Infine, aggiungere queste quattro pagine come voci al Web.sitemap file. 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, passare un momento per visualizzare il sito Web delle esercitazioni tramite un browser. Il menu a sinistra include ora elementi per la modifica, l'inserimento e l'eliminazione di esercitazioni.

La mappa del sito include ora voci per l'miglioramento delle esercitazioni di GridView

Figura 3: La mappa del sito include ora le voci per il miglioramento delle esercitazioni di GridView

Passaggio 2: Visualizzazione dei fornitori in un controllo GridView

Per questa esercitazione è possibile creare un controllo GridView che elenca i fornitori degli Stati Uniti, con ogni riga GridView che fornisce 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 questa attività può sembrare semplice, ci sono numerose sottigliezze che lo rendono particolarmente difficile. Prima di approfondire queste sottigliezze, è prima di tutto possibile ottenere un elenco di GridView sui fornitori.

Iniziare aprendo la RadioButtonField.aspx pagina nella EnhancedGridView cartella trascinando gridView dalla casella degli strumenti nella Designer. Impostare GridView su IDSuppliers e, dal relativo smart tag, scegliere di creare una nuova origine dati. In particolare, creare un oggetto ObjectDataSource denominato SuppliersDataSource che esegue il pull dei dati dall'oggetto SuppliersBLL .

Creare un nuovo oggettoDataSource denominato SuppliersDataSource

Figura 4: Creare un nuovo oggettoDataSource denominato SuppliersDataSource (fare clic per visualizzare l'immagine full-size)

Screenshot della finestra Configura origine dati - SuppliersDataSource con l'oggetto business SuppliersBLL selezionato e il pulsante Avanti evidenziato.

Figura 5: Configurare ObjectDataSource per usare la classe (fare clic per visualizzare l'immagineSuppliersBLL full-size)

Poiché si vuole elencare solo i fornitori negli Stati Uniti, scegliere il GetSuppliersByCountry(country) metodo dall'elenco a discesa nella scheda SELECT.

Screenshot della finestra Configura origine dati - SuppliersDataSource con la scheda SELECT aperta. L'opzione del metodo GetSupplierByCountry è selezionata e il pulsante Next è evidenziato.

Figura 6: Configurare ObjectDataSource per usare la classe (fare clic per visualizzare l'immagineSuppliersBLL full-size)

Nella scheda UPDATE selezionare l'opzione (Nessuno) e fare clic su Avanti.

Screenshot della finestra Configura origine dati - SuppliersDataSource con la scheda UPDATE aperta. L'opzione metodo (None) è selezionata e il pulsante Next è evidenziato.

Figura 7: Configurare ObjectDataSource per usare la classe (fare clic per visualizzare l'immagineSuppliersBLL full-size)

Poiché il metodo accetta un parametro, la GetSuppliersByCountry(country) procedura guidata Configura origine dati richiede l'origine di tale parametro. Per specificare un valore con codice rigido ( USA, in questo esempio), lasciare l'elenco a discesa Origine parametro impostato su None e immettere il valore predefinito nella casella di testo. Fare clic su Fine per completare la procedura guidata.

Usare USA come valore predefinito per il parametro paese

Figura 8: Usare USA come valore predefinito per il country parametro (fare clic per visualizzare l'immagine full-size)

Al termine della procedura guidata, GridView includerà un oggetto BoundField per ognuno dei campi dati del fornitore. Rimuovere tutti gli elementi CompanyName, Citye Country BoundFields e rinominare la CompanyName proprietà BoundFields HeaderText in Supplier. Dopo aver eseguito 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 selezionati nella stessa pagina dell'elenco dei fornitori o in una pagina diversa. Per supportare questa operazione, aggiungere due controlli Web Button alla pagina. Ho impostato i ID due pulsanti ListProducts su e SendToProducts, con l'idea che quando ListProducts si fa clic su un postback si verificherà un postback e i prodotti del fornitore selezionato verranno elencati nella stessa pagina, ma quando SendToProducts viene fatto clic, l'utente verrà spostato in un'altra pagina che elenca i prodotti.

La Suppliers figura 9 mostra GridView e i due controlli Web Button quando vengono visualizzati tramite un browser.

I fornitori degli Stati Uniti hanno il nome, la città e le informazioni sul paese elencate

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 dimensioni complete)

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. Manca ancora una colonna di pulsanti di opzione, tuttavia. Purtroppo, GridView non include un oggetto RadioButtonField predefinito, altrimenti potremmo semplicemente aggiungerlo alla griglia ed essere fatto. È invece possibile aggiungere un ModelloField e configurarne ItemTemplate il rendering per eseguire il rendering di un pulsante di opzione, con conseguente pulsante di opzione per ogni riga gridView.

Inizialmente, è possibile presupporre che l'interfaccia utente desiderata possa essere implementata aggiungendo un controllo Web RadioButton all'oggetto ItemTemplate 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. Vale a dire, un utente finale è in grado di selezionare più pulsanti di opzione contemporaneamente da GridView.

Anche se l'uso di un controllo Web TemplateField di RadioButton non offre le funzionalità necessarie, è possibile implementare questo approccio, perché è utile esaminare il motivo per cui i pulsanti di opzione risultanti non sono raggruppati. Iniziare aggiungendo 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 nella ItemTemplate casella degli strumenti (vedere la figura 10). Impostare la proprietà RadioButton ID su RowSelector e la GroupName proprietà su SuppliersGroup.

Aggiungere un controllo Web RadioButton all'elementoTemplate

Figura 10: Aggiungere un controllo Web RadioButton all'oggetto ItemTemplate (fare clic per visualizzare l'immagine a dimensioni complete)

Dopo aver effettuato queste aggiunte tramite la Designer, 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 è ciò che viene usato 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 GroupName proprietà specifica il valore dell'attributo del pulsante di name opzione di cui è stato eseguito il rendering. Il browser esamina gli attributi dei pulsanti di opzione per determinare i raggruppamenti dei pulsanti name di opzione.

Con il controllo Web RadioButton aggiunto all'oggetto ItemTemplate, visitare questa pagina tramite un browser e fare clic sui pulsanti di opzione nelle righe della griglia. Si noti come i pulsanti di opzione non sono raggruppati, rendendo possibile selezionare tutte le righe, come illustrato nella figura 11.

I pulsanti di opzione di GridView non sono raggruppati

Figura 11: i pulsanti di opzione gridView s Non sono raggruppati (fare clic per visualizzare l'immagine a dimensioni complete)

Il motivo per cui i pulsanti di opzione non sono raggruppati è perché i relativi attributi di rendering name sono diversi, nonostante l'impostazione della stessa GroupName proprietà. Per visualizzare queste differenze, eseguire una visualizzazione/origine dal browser ed esaminare il markup del pulsante di opzione:

<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 come sia gli attributi e id non siano i name valori esatti come specificato nella Finestra Proprietà, ma vengono prependati con un numero di altri ID valori. I valori aggiuntivi ID aggiunti alla parte anteriore del rendering id e name degli attributi sono i ID controlli padre dei pulsanti GridViewRowID di opzione s, gridView s ID, il controllo Contenuto s IDe il modulo Web s ID. Questi ID vengono aggiunti in modo che ogni controllo Web di cui è stato eseguito il rendering in GridView abbia valori univoci id e name .

Ogni controllo di cui è stato eseguito il rendering necessita di un diverso name e id , poiché questo è il modo in cui il browser identifica in modo univoco ogni controllo sul lato client e come identifica al server Web l'azione o la modifica apportata al postback. Si supponga, ad esempio, di voler eseguire codice lato server ogni volta che è stato modificato lo stato di controllo di un controllo radiobutton. A tale scopo, impostare la proprietà true RadioButton su AutoPostBack e creare un gestore eventi per l'eventoCheckChanged. Tuttavia, se il rendering name e id i valori per tutti i pulsanti di opzione sono uguali, al postback non è stato possibile determinare il pulsante di opzione specifico selezionato.

Il breve è che non è possibile creare una colonna di pulsanti di opzione in un controllo GridView usando il controllo Web RadioButton. Al contrario, è necessario usare tecniche piuttosto arcaiche per garantire che il markup appropriato venga inserito in ogni riga gridView.

Nota

Analogamente al 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.If you are interested in more, see K. Scott Allen s blog entry Web Controls and HTML Controls.

Uso di un controllo letterale per inserire il markup del pulsante di opzione

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 lato client). Dopo che un utente seleziona un pulsante di opzione e pubblica la pagina, il browser restituirà il valore dell'attributo del pulsante di value opzione selezionato. Pertanto, ogni pulsante di opzione richiederà un attributo univoco value . Infine, al postback è necessario assicurarsi di aggiungere l'attributo checked a un pulsante di opzione selezionato, altrimenti dopo che l'utente effettua una selezione e esegue il postback, i pulsanti di opzione torneranno allo stato predefinito (tutti deselezionati).

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 descritta per la prima volta nell'esercitazione Uso di TemplateFields nell'esercitazione Sul controllo GridView . In questo caso potrebbe essere simile al seguente:

<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>' 
    name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />

GetUniqueRadioButton In questo caso, e GetRadioButtonValue sarebbero i metodi definiti nella classe code-behind che restituivano i valori appropriati id e value di attributo per ogni pulsante di opzione. Questo approccio funziona bene per l'assegnazione degli id attributi e value , ma si riduce quando è necessario specificare il valore dell'attributo checked perché la sintassi di associazione dati viene eseguita solo quando i dati vengono associati per la prima volta a 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 rimbalzato in modo esplicito nell'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, vi incoraggio a provare a usare l'approccio precedente e usarlo fino al punto in cui ci si blocca. 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 e di basso livello in un modello e all'approccio che verrà usato per questa esercitazione consiste nell'aggiungere un controllo Letterale al modello. Quindi, nel gestore eventi o RowCreatedRowDataBound gridView, è possibile accedere al controllo Literal a livello di codice e la relativa Text proprietà impostata sul markup da generare.

Per iniziare, rimuovere il controllo RadioButton da TemplateField s ItemTemplate, sostituendolo con un controllo Literal. Impostare il controllo Letterale su IDRadioButtonMarkup.

Aggiungere un controllo letterale a ItemTemplate

Figura 12: Aggiungere un controllo letterale a (fare clic per visualizzare l'immagineItemTemplate 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 ripresi in GridView. Ciò significa che anche in un postback quando i dati vengono ricaricati dallo stato di visualizzazione, l'evento RowCreated viene ancora attivato e questo è il motivo per cui viene usato invece di RowDataBound (che viene generato solo quando i dati sono associati in modo esplicito al controllo Web dei dati).

In questo gestore eventi si vuole procedere solo se si tratta di una riga di dati. Per ogni riga di dati si vuole fare riferimento a livello di codice al RadioButtonMarkup controllo Literal e impostarne Text la proprietà sul markup da generare. Come illustrato nel codice seguente, il markup generato crea un pulsante di opzione il cui name attributo è impostato su SuppliersGroup, il cui id attributo è impostato su RowSelectorX, dove X è l'indice della riga GridView e il cui value attributo è 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 si seleziona una riga GridView e si verifica un postback, si è interessati al SupplierID fornitore selezionato. Pertanto, si potrebbe pensare che il valore di ogni pulsante di opzione deve 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. GridView, ad esempio, elenca solo i fornitori negli Stati Uniti. Tuttavia, se l'oggetto SupplierID viene passato direttamente dal pulsante di opzione, cosa impedisce a un utente malizioso di modificare il SupplierID valore inviato al postback? Usando l'indice di riga come valuee quindi recuperando il SupplierID postback dalla DataKeys raccolta, è possibile assicurarsi che l'utente usi solo uno dei SupplierID valori associati a una delle righe gridView.

Dopo aver aggiunto questo codice del gestore eventi, eseguire un minuto per testare la pagina in un browser. In primo luogo, si noti che è possibile selezionare un solo pulsante di opzione 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 lo stato iniziale, ovvero al postback, il pulsante di opzione selezionato non è più selezionato. Per risolvere questo problema, è necessario aumentare il RowCreated gestore eventi in modo che controlli l'indice del pulsante di opzione selezionato inviato dal postback e aggiusta l'attributo checked="checked" al markup generato delle corrispondenze dell'indice di riga.

Quando si verifica un postback, il browser restituisce e namevalue del pulsante di opzione selezionato. Il valore può essere recuperato a livello di codice usando 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 di cui è stato name eseguito il rendering dei pulsanti di opzione in GridView è SuppliersGroup, quando la pagina Web viene inviata di nuovo al SuppliersGroup=valueOfSelectedRadioButton server Web (insieme agli altri campi modulo). È quindi possibile accedere a queste informazioni dalla Request.Form proprietà usando : Request.Form["SuppliersGroup"].

Poiché sarà necessario determinare l'indice del pulsante di opzione selezionato non solo nel RowCreated gestore eventi, ma nei gestori eventi per i Click controlli Web Button, è possibile aggiungere una SuppliersSelectedIndex proprietà alla classe code-behind che restituisce -1 se non è stato selezionato alcun pulsante di opzione e l'indice selezionato se è selezionato uno dei pulsanti di opzione.

private int SuppliersSelectedIndex
{
    get
    {
        if (string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))
            return -1;
        else
            return Convert.ToInt32(Request.Form["SuppliersGroup"]);
    }
}

Con questa proprietà aggiunta, si sa di aggiungere il checked="checked" markup nel RowCreated gestore eventi 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 è stata aggiunta una colonna di pulsanti di opzione raggruppati a GridView che consente di selezionare e ricordare una singola riga gridView tra postback. I 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.

Nota

Invece di usare un campo Template (lo stato attivo di questo lungo passaggio 3), è possibile creare una classe personalizzata DataControlField che esegua il rendering dell'interfaccia utente e delle 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 usando solo la sintassi dichiarativa e renderebbe anche più semplice replicare le funzionalità in altre pagine Web e in altre applicazioni Web.

Se hai mai creato controlli personalizzati, compilati in ASP.NET, tuttavia, sai che questa operazione richiede una quantità equa di legwork e porta con sé una serie di sottigliezze e casi limite che devono essere gestiti con attenzione. Di conseguenza, verrà creata una colonna di pulsanti di opzione come classe personalizzata DataControlField per il momento e attenersi all'opzione TemplateField. Forse sarà possibile 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 potremmo preferire di farlo nella stessa pagina. Prima di tutto esaminiamo come visualizzare i prodotti in una pagina separata; Nel passaggio 5 si esaminerà l'aggiunta di un controllo GridView per RadioButtonField.aspx 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 nell'esercitazione Filtro master/dettaglio tra due pagine e visualizza i prodotti per il fornitore il cui SupplierID viene passato attraverso il campo querystring denominato SupplierID.

Per fornire questa funzionalità, creare un gestore eventi per l'evento SendToProducts Button s Click . Nel passaggio 3 è stata aggiunta la SuppliersSelectedIndex proprietà , che restituisce l'indice della riga il cui pulsante di opzione è selezionato. Il corrispondente SupplierID può essere recuperato dalla raccolta di DataKeys 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 perfettamente, purché uno dei pulsanti di opzione sia selezionato da GridView. Se, inizialmente, GridView non dispone di pulsanti di opzione selezionati e l'utente fa clic sul SendToProducts pulsante, SuppliersSelectedIndex sarà -1, che causerà la generazione di un'eccezione perché -1 non è compreso nell'intervallo di indici della DataKeys raccolta. Questo non è un problema, tuttavia, se si decide di aggiornare il RowCreated gestore eventi come descritto nel passaggio 3 in modo da avere il primo pulsante di opzione in GridView inizialmente selezionato.

Per contenere un SuppliersSelectedIndex valore di -1, aggiungere un controllo Web Etichetta alla pagina sopra GridView. Impostare la ID relativa proprietà su ChooseSupplierMsg, la relativa CssClass proprietà su Warning, le EnableViewState relative proprietà e Visible su falsee la relativa Text proprietà su 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 EnableViewState proprietà e Visible su false, il rendering dell'oggetto Label non viene eseguito ad eccezione solo dei postback in cui la proprietà del Visible controllo è impostata a livello di codice su true.

Aggiungere un controllo Web Etichetta sopra GridView

Figura 13: Aggiungere un controllo Web etichetta sopra GridView (fare clic per visualizzare l'immagine a dimensione intera)

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 . Questo ti porterà in 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.

L'etichetta ChooseSupplierMsg viene visualizzata se non è selezionato alcun fornitore

Figura 14: L'etichetta ChooseSupplierMsg viene visualizzata se non è selezionato alcun fornitore (fare clic per visualizzare l'immagine a dimensione intera)

I prodotti dei fornitori selezionati vengono visualizzati in ProductsForSupplierDetails.aspx

Figura 15: I prodotti dei fornitori selezionati vengono 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 del fornitore selezionati possono essere visualizzati nella stessa pagina. Per illustrare questo problema, verrà aggiunto un altro controllo GridView per RadioButtonField.aspx visualizzare i prodotti del fornitore selezionato.

Poiché si vuole che questo controllo GridView dei prodotti venga visualizzato solo dopo che un fornitore è stato selezionato, aggiungere un controllo Web Panel sotto Suppliers GridView, impostandone ProductsBySupplierPanelID su e la relativa Visible proprietà su false. All'interno del pannello aggiungere il testo Products per il fornitore selezionato, seguito da un controllo GridView denominato ProductsBySupplier. Dallo smart tag gridView scegliere di associarlo a un nuovo ObjectDataSource denominato ProductsBySupplierDataSource.

Associare ProductsBySupplier GridView a un nuovo ObjectDataSource

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.

Configurare ObjectDataSource per l'uso del metodo GetProductsBySupplierID(supplierID)

Figura 17: Configurare ObjectDataSource per l'uso del metodo (fare clic per visualizzare l'immagineGetProductsBySupplierID(supplierID) a dimensione intera)

Impostare il Drop-Down Elenchi su (Nessuno) nelle schede UPDATE, INSERT e DELETE

Figura 18: Impostare il Drop-Down Elenchi 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 prevede un parametro di input, la procedura guidata Crea origine dati richiede di specificare l'origine per il valore del parametro.

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 ObjectDataSource.Selecting Fare riferimento all'esercitazione Impostazione dei valori dei parametri di ObjectDataSource a livello di codice per un aggiornamento per l'assegnazione di valori a livello di codice ai parametri di ObjectDataSource.

In alternativa, è possibile usare controlParameter e fare riferimento alla Suppliers proprietà gridView (SelectedValuevedere la figura 19). La proprietà gridView restituisce SelectedValue il DataKey valore corrispondente alla SelectedIndex proprietà . 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 SelectedIndex, il record selezionato assumerà l'oggetto SelectedRowStyle definito nel DataWebControls tema (sfondo giallo).

Usare un oggetto ControlParameter per specificare il valore SelectedValue di GridView come origine dei parametri

Figura 19: Usare un controlParameter per specificare il valore SelectedValue di GridView come origine parametro (fare clic per visualizzare l'immagine a dimensione intera)

Al termine della procedura guidata, Visual Studio aggiungerà automaticamente campi per i campi dati del prodotto. Rimuovere tutti gli elementi , ProductNameCategoryNamee UnitPrice BoundFields e modificare le HeaderText proprietà 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 ProductsBySupplierPanel proprietà Panel s Visible su true quando si fa clic sul ListProducts pulsante.SelectedSuppliersIndex A tale scopo, creare un gestore eventi per l'evento ListProducts del Click controllo Web Button 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, viene visualizzato e ProductsBySupplierPanel la proprietà gridView s SelectedIndex viene aggiornata.

La figura 20 mostra i risultati dopo che il fornitore Bigfoot Breweries è stato selezionato e il pulsante Mostra prodotti nella pagina è stato selezionato.

I prodotti forniti da Bigfoot Breweries sono elencati nella stessa pagina

Figura 20: I prodotti forniti da Bigfoot Breweries sono elencati nella stessa pagina (fare clic per visualizzare l'immagine a dimensione intera)

Riepilogo

Come descritto nell'esercitazione Master/Detail Using a Selectable Master GridView with a Details DetailView , i record possono essere selezionati da un controllo GridView usando un commandField la cui ShowSelectButton proprietà è impostata su true. Tuttavia, commandField visualizza i pulsanti come pulsanti, collegamenti o immagini regolari. Un'interfaccia utente alternativa per la selezione di righe consiste nel fornire un pulsante di opzione o una casella di controllo in ogni riga di GridView. In questa esercitazione è stato illustrato come aggiungere una colonna di pulsanti di opzione.

Sfortunatamente, l'aggiunta di una colonna di pulsanti di opzione non è semplice 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, è possibile assegnare l'attenzione all'aggiunta di 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, 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 è David Suru. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.