Delen via


Een GridView-kolom met radioknoppen toevoegen (C#)

door Scott Mitchell

PDF downloaden

In deze zelfstudie wordt uitgelegd hoe u een kolom met keuzerondjes toevoegt aan een GridView-besturingselement om de gebruiker een intuïtievere manier te bieden om één rij van de GridView te selecteren.

Introductie

Het GridView-besturingselement biedt veel ingebouwde functionaliteit. Het bevat een aantal verschillende velden voor het weergeven van tekst, afbeeldingen, hyperlinks en knoppen. Het ondersteunt sjablonen voor verdere aanpassing. Met een paar muisklikken is het mogelijk om een GridView te maken waarin elke rij kan worden geselecteerd via een knop of om bewerkings- of verwijdermogelijkheden in te schakelen. Ondanks de overvloed aan opgegeven functies, zullen er vaak situaties zijn waarin aanvullende, niet-ondersteunde functies moeten worden toegevoegd. In deze zelfstudie en de volgende twee onderzoeken we hoe we de functionaliteit van GridView kunnen verbeteren om extra functies toe te voegen.

Deze handleiding en de volgende focussen op de verbetering van het selecteren van rijen. Zoals onderzocht wordt in de Hoofd/Detail waarbij een Selecteerbare Hoofd GridView wordt gebruikt met een Details DetailView, kunnen we een CommandField toevoegen aan de GridView met een Select-knop. Wanneer erop wordt geklikt, vindt een postback plaats en wordt de GridView-eigenschap SelectedIndex bijgewerkt naar de index van de rij waarop de Select-knop is aangeklikt. In de zelfstudie Master/Detail Using a Selectable Master GridView with a Details DetailView hebben we gezien hoe je deze mogelijkheid kunt gebruiken om gegevens weer te geven voor de geselecteerde rij in de GridView.

Hoewel de knop Selecteren in veel situaties werkt, werkt deze mogelijk niet zo goed voor anderen. In plaats van een knop te gebruiken, worden vaak twee andere gebruikersinterface-elementen gebruikt voor selectie: het keuzerondje en het selectievakje. We kunnen de GridView aanpassen, zodat in plaats van een knop Selecteren elke rij een keuzerondje of selectievakje bevat. In scenario's waarin de gebruiker slechts één van de GridView-records kan selecteren, kan de radioknop de voorkeur hebben boven de Selecteren-knop. In situaties waarin de gebruiker mogelijk meerdere records kan selecteren, zoals in een web-e-mailtoepassing waar een gebruiker meerdere berichten wil selecteren om te verwijderen, biedt het selectievakje functionaliteit die niet beschikbaar is via de gebruikersinterfaces van de Select-knop of keuzerondjes.

In deze handleiding wordt uitgelegd hoe u een kolom met keuzerondjes toevoegt aan de GridView. In de volgende handleiding wordt het gebruik van selectievakjes verkend.

Stap 1: het verbeteren van de GridView-webpagina's maken

Voordat we beginnen de GridView te verbeteren om een kolom met keuzerondjes toe te voegen, nemen we eerst de tijd om de ASP.NET-pagina's in ons websiteproject te maken die we nodig hebben voor deze tutorial en de volgende twee. Begin met het toevoegen van een nieuwe map met de naam EnhancedGridView. Voeg vervolgens de volgende ASP.NET pagina's toe aan die map en zorg ervoor dat u elke pagina koppelt aan de Site.master basispagina:

  • Default.aspx
  • RadioButtonField.aspx
  • CheckBoxField.aspx
  • InsertThroughFooter.aspx

ASP.NET-pagina's toevoegen voor de SqlDataSource-Related-tutorials

Afbeelding 1: De ASP.NET pagina's voor de zelfstudies voor SqlDataSource-Related toevoegen

Net als in de andere mappen, zal Default.aspx in de map EnhancedGridView de zelfstudies in zijn sectie weergeven. Zoals u weet, biedt het SectionLevelTutorialListing.ascx gebruikersbeheer deze functionaliteit. Voeg daarom deze gebruikerscontrole toe aan Default.aspx door het vanuit de Solution Explorer naar de ontwerpweergave van de pagina te slepen.

Voeg de SectionLevelTutorialListing.ascx User Control toe aan Default.aspx

Afbeelding 2: Het gebruikersbesturingselement toevoegen SectionLevelTutorialListing.ascx aan Default.aspx (klik om de afbeelding op volledige grootte weer te geven)

Voeg tot slot deze vier pagina's toe als vermeldingen aan het Web.sitemap bestand. Specifiek, voeg de volgende markup toe na het gebruiken van het besturingselement SqlDataSource <siteMapNode>:

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

Neem na het bijwerken Web.sitemap even de moeite om de tutorialswebsite via een browser te bekijken. Het menu aan de linkerkant bevat nu items voor bewerken, invoegen, en verwijderen van tutorials.

Het siteoverzicht bevat nu vermeldingen voor het verbeteren van de GridView-zelfstudies

Afbeelding 3: Het siteoverzicht bevat nu items voor de handleidingen 'Enhancing the GridView'

Stap 2: de leveranciers weergeven in een GridView

Voor deze zelfstudie laten we een GridView bouwen waarin de leveranciers uit de Verenigde Staten worden vermeld, waarbij elke GridView-rij een radioknop biedt. Nadat een leverancier is geselecteerd via het keuzerondje, kan de gebruiker de producten van de geselecteerde leverancier bekijken door op een knop te klikken. Hoewel deze taak triviaal kan klinken, zijn er een aantal subtiliteiten die het bijzonder lastig maken. Voordat we dieper ingaan op deze subtiliteiten, gaan we eerst een GridView-lijst maken met de leveranciers.

Open eerst de RadioButtonField.aspx pagina in de EnhancedGridView map door een GridView vanuit de Werkset naar de ontwerpfunctie te slepen. Stel de GridView's ID in op Suppliers en kies vanuit het contextmenu ervoor om een nieuwe gegevensbron te maken. Maak met name een ObjectDataSource met de naam SuppliersDataSource die de gegevens van het SuppliersBLL object ophaalt.

Een nieuwe ObjectDataSource maken met de naam SuppliersDataSource

Afbeelding 4: Een nieuwe ObjectDataSource maken met de naam SuppliersDataSource (Klik hier om de volledige afbeelding weer te geven)

Schermopname van het venster Gegevensbron configureren - SuppliersDataSource met het zakelijke object SuppliersBLL geselecteerd en de knop Volgende gemarkeerd.

Afbeelding 5: De ObjectDataSource configureren om de SuppliersBLL klasse te gebruiken (klik om de afbeelding op volledige grootte weer te geven)

Omdat we alleen die leveranciers in de VS willen vermelden, kiest u de GetSuppliersByCountry(country) methode in de vervolgkeuzelijst op het tabblad SELECT.

Schermopname van het venster Gegevensbron configureren - SuppliersDataSource met het tabblad SELECT geopend. De methodeoptie GetSupplierByCountry is geselecteerd en de knop Volgende is gemarkeerd.

Afbeelding 6: De ObjectDataSource configureren om de SuppliersBLL klasse te gebruiken (klik om de afbeelding op volledige grootte weer te geven)

Selecteer op het tabblad BIJWERKEN de optie (Geen) en klik op Volgende.

Schermopname van het venster Gegevensbron configureren - SuppliersDataSource met het tabblad UPDATE geopend. De methodeoptie (Geen) is geselecteerd en de knop Volgende is gemarkeerd.

Afbeelding 7: De ObjectDataSource configureren om de SuppliersBLL klasse te gebruiken (klik om de afbeelding op volledige grootte weer te geven)

Omdat de GetSuppliersByCountry(country) methode een parameter accepteert, vraagt de wizard Gegevensbron configureren ons om de bron van die parameter. Als u een in code vastgelegde waarde (VS) wilt opgeven, laat u in dit voorbeeld de vervolgkeuzelijst Parameterbron ingesteld op Geen en voert u de standaardwaarde in het tekstvak in. Klik op Voltooien om de wizard te voltooien.

Gebruik 'VS' als de standaardwaarde voor de parameter voor land

Afbeelding 8: Gebruik USA als de standaardwaarde voor de country parameter (klik om de afbeelding op volledige grootte weer te geven)

Nadat de wizard is voltooid, bevat GridView een BoundField voor elk van de gegevensvelden van de leverancier. Verwijder alle, behalve de CompanyName, City, en Country BoundFields, en hernoem de eigenschap CompanyName van de HeaderText BoundFields naar Leverancier. Nadat u dit hebt gedaan, moeten de declaratieve syntaxis GridView en ObjectDataSource er ongeveer als volgt uitzien.

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

Voor deze zelfstudie kunnen we de gebruiker toestaan de producten van de geselecteerde leveranciers weer te geven op dezelfde pagina als de lijst met leveranciers of op een andere pagina. Hiervoor voegt u twee knopwebbesturingselementen toe aan de pagina. Ik heb de ID-waarden van deze twee knoppen ingesteld op ListProducts en SendToProducts, met het idee dat wanneer ListProducts wordt aangeklikt, er een postback zal plaatsvinden en de producten van de geselecteerde leverancier op dezelfde pagina worden weergegeven. Wanneer op SendToProducts wordt geklikt, wordt de gebruiker naar een andere pagina geleid die de producten toont.

In afbeelding 9 ziet u de Suppliers rasterweergave en de twee knopwebbesturingselementen wanneer deze worden weergegeven via een browser.

Deze leveranciers uit de VS hebben hun naam, plaats en landinformatie vermeld

Afbeelding 9: Deze leveranciers uit de VERENIGDE Staten hebben hun naam, plaats en landinformatie vermeld (klik om de volledige afbeelding weer te geven)

Stap 3: Toevoegen van een kolom met selectievakjes

Op dit moment bevat de Suppliers GridView drie BoundFields met de bedrijfsnaam, plaats en land van elke leverancier in de VS. Er ontbreekt echter nog steeds een kolom met keuzerondjes. Helaas bevat de GridView geen ingebouwde RadioButtonField, anders konden we dat gewoon aan de grid toevoegen en klaar zijn. In plaats daarvan kunnen we een TemplateField toevoegen en de ItemTemplate configureren om een keuzerondje weer te geven, wat resulteert in een keuzerondje voor elke GridView-rij.

In eerste instantie gaan we ervan uit dat de gewenste gebruikersinterface kan worden geïmplementeerd door een RadioButton-webbesturing toe te voegen aan het ItemTemplate van een TemplateField. Hoewel dit inderdaad een enkele radioknop toevoegt aan elke rij van de GridView, kunnen de radioknoppen niet worden gegroepeerd en zijn ze daarom niet onderling uitsluitend. Dat wil zeggen dat een eindgebruiker meerdere radioknoppen tegelijk kan selecteren vanuit de GridView.

Hoewel het gebruik van een TemplateField van RadioButton Web-besturingselementen niet de functionaliteit biedt die we nodig hebben, gaan we deze aanpak implementeren, omdat het de moeite waard is om te onderzoeken waarom de resulterende keuzerondjes niet zijn gegroepeerd. Begin met het toevoegen van een TemplateField aan de Leveranciers GridView, waardoor dit het meest linkse veld is. Klik vervolgens vanuit de smarttag van de GridView op de koppeling "Sjablonen bewerken", en sleep een RadioButton Web-besturingselement uit de Werkset naar het sjabloonveld ItemTemplate (zie Afbeelding 10). Stel de eigenschap van de RadioButton in op IDRowSelector en de eigenschap op GroupNameSuppliersGroup.

Een RadioButton-web besturingselement toevoegen aan de ItemTemplate

Afbeelding 10: Een RadioButton-webbesturingselement toevoegen aan de ItemTemplate knop (Klik om de afbeelding op volledige grootte weer te geven)

Nadat u deze toevoegingen hebt doorgevoerd via de ontwerpfunctie, moet de markering van GridView er ongeveer als volgt uitzien:

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

De eigenschap RadioButton GroupName wordt gebruikt om een reeks keuzerondjes te groeperen. Alle radioknoppen met dezelfde GroupName waarde worden als gegroepeerd beschouwd; er kan slechts één radioknop tegelijk in een groep worden geselecteerd. De GroupName eigenschap specificeert de waarde voor het name kenmerk van het weergegeven radioknopje. De browser onderzoekt de attributen van radioknoppen name om de groeperingen van radioknoppen te bepalen.

Met de toevoeging van de RadioButton-webcontrol aan de ItemTemplate, ga naar deze pagina via een browser en klik op de keuzerondjes in de rasterrijen. Merk op hoe de radioknoppen niet zijn gegroepeerd, waardoor u alle rijen kunt selecteren, zoals in afbeelding 11 wordt weergegeven.

De keuzerondjes van de GridView zijn niet gegroepeerd

Afbeelding 11: De keuzerondjes van de rasterweergave zijn niet gegroepeerd (Klik om de afbeelding volledig weer te geven)

Omdat de weergegeven name kenmerken verschillen, ondanks dezelfde GroupName eigenschapinstelling, zijn de keuzerondjes niet gegroepeerd. Als u deze verschillen wilt zien, doe een weergave/bron vanuit de browser en bekijk de markeringen van de radioknop.

<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" />

U ziet dat zowel de als de nameid kenmerken niet de exacte waarden zijn zoals opgegeven in het venster Eigenschappen, maar worden voorafgegaan door een aantal andere ID waarden. De extra ID waarden die aan de voorzijde van de gerenderde id en name attributen worden toegevoegd, zijn de ID s van de bovenliggende besturingselementen van de keuzerondjes, de GridViewRow s ID s, de GridView s ID s, het inhoudsbesturingselement s ID en de webformulier s ID. Deze ID s worden toegevoegd zodat elk gerenderd webbesturingselement in de GridView een unieke id en name waarden heeft.

Elk gerenderd besturingselement heeft unieke name en id omdat dit is hoe de browser elk besturingselement aan de clientzijde uniek identificeert en hoe het aan de webserver meedeelt welke actie of wijziging heeft plaatsgevonden bij het terugzenden. Stel dat we bepaalde code aan de serverzijde willen uitvoeren wanneer de status RadioButton is gewijzigd. We kunnen dit bereiken door de eigenschap van de RadioButton in AutoPostBack in te stellen op true en een event-handler voor de CheckChanged gebeurtenis te maken. Als de weergegeven name- en id-waarden voor alle keuzerondjes echter hetzelfde waren, konden we na het versturen niet bepalen op welke specifieke RadioButton werd geklikt.

Het korte deel is dat we geen kolom met keuzerondjes kunnen maken in een GridView met behulp van het webbesturingselement RadioButton. In plaats daarvan moeten we eerder archaische technieken gebruiken om ervoor te zorgen dat de juiste opmaak wordt geïnjecteerd in elke GridView-rij.

Opmerking

Net als het RadioButton Web-besturingselement bevat het HTML-besturingselement voor radioknoppen, wanneer het aan een sjabloon wordt toegevoegd, het unieke name kenmerk, waardoor de radioknoppen in het raster niet gegroepeerd zijn. Als u niet bekend bent met HTML-besturingselementen, kunt u deze opmerking negeren, omdat HTML-besturingselementen zelden worden gebruikt, met name in ASP.NET 2.0. Maar als u meer wilt weten, raadpleegt u het blogbericht webbesturingselementen en HTML-besturingselementen van K. Scott Allen.

Een letterlijk besturingselement gebruiken om keuzerondjemarkeringen in te voeren

Om alle keuzerondjes in de GridView correct te groeperen, moeten we de markup van de keuzerondjes handmatig in de ItemTemplate invoegen. Elk radioknop heeft hetzelfde name kenmerk nodig, maar moet een uniek id kenmerk hebben (in geval we een radioknop willen benaderen via clientscripts). Nadat een gebruiker een keuzerondje heeft geselecteerd en de pagina verstuurd, stuurt de browser de waarde van het geselecteerde keuzerondje value terug. Daarom heeft elk keuzerondje een uniek value kenmerk nodig. Ten slotte moeten we ervoor zorgen dat bij terugzending het checked-kenmerk wordt toegevoegd aan het geselecteerde keuzerondje. Anders zullen de keuzerondjes, nadat de gebruiker een selectie heeft gemaakt en de pagina opnieuw is geladen, terugkeren naar hun standaardstatus (allemaal niet-geselecteerd).

Er zijn twee benaderingen die kunnen worden gebruikt om markeringen op laag niveau in een sjabloon te injecteren. Een daarvan is een combinatie van markeringen en aanroepen naar opmaakmethoden die zijn gedefinieerd in de code-behind-klasse. Deze techniek is voor het eerst besproken in de zelfstudie Sjabloonvelden in de GridView Control gebruiken. In ons geval kan het er ongeveer als volgt uitzien:

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

Hier zouden GetUniqueRadioButton en GetRadioButtonValue methoden zijn gedefinieerd in de code-behind-klasse die de juiste id en value attribuutwaarden voor elke radioknop retourneren. Deze benadering werkt goed voor het toewijzen van de id en value kenmerken, maar valt kort wanneer u de checked kenmerkwaarde wilt opgeven, omdat de syntaxis van de gegevensbinding alleen wordt uitgevoerd wanneer gegevens voor het eerst zijn gebonden aan de GridView. Als de weergavestatus van GridView daarom is ingeschakeld, worden de opmaakmethoden alleen geactiveerd wanneer de pagina voor het eerst wordt geladen (of wanneer de GridView expliciet wordt teruggezet naar de gegevensbron), en daarom wordt de functie waarmee het checked kenmerk wordt ingesteld, niet aangeroepen op postback. Het is een nogal subtiel probleem en een beetje buiten het bereik van dit artikel, dus ik laat het hier achter. Ik moedig u echter aan om de bovenstaande benadering te gebruiken en door te werken tot het punt waar u vastloopt. Hoewel een dergelijke oefening u niet dichter bij een werkende versie krijgt, helpt dit om een dieper inzicht te krijgen in de GridView en de levenscyclus van gegevensbinding.

De andere benadering voor het injecteren van aangepaste markeringen op laag niveau in een sjabloon en de benadering die we voor deze zelfstudie gebruiken, is het toevoegen van een letterlijk besturingselement aan de sjabloon. Vervolgens kan in de GridView RowCreated- of RowDataBound-gebeurtenis-handler het Literal-besturingselement programmatisch worden benaderd en kan de eigenschap ervan worden ingesteld op de markup om uit te zenden.

Start met het verwijderen van de RadioButton uit de TemplateFields ItemTemplate, waarbij u het vervangt door een Literal-besturingselement. Stel de letterlijke besturingselementen in ID op RadioButtonMarkup.

Voeg een Literal Control toe aan de ItemTemplate

Afbeelding 12: Voeg een literal control toe aan de ItemTemplate (afbeelding, klik om de afbeelding op volledige grootte weer te geven)

Maak vervolgens een gebeurtenis-handler voor de GridView-gebeurtenis RowCreated . De RowCreated gebeurtenis wordt eenmaal geactiveerd voor elke rij die is toegevoegd, ongeacht of de gegevens worden hersteld naar de GridView. Dat betekent dat zelfs bij een postback wanneer de gegevens opnieuw worden geladen vanuit de weergavestatus, de RowCreated gebeurtenis nog steeds wordt geactiveerd en dit is de reden waarom we deze gebruiken in plaats van RowDataBound (die alleen wordt geactiveerd wanneer de gegevens expliciet zijn gebonden aan het gegevenswebbeheer).

In deze gebeurtenis-handler willen we alleen doorgaan als we te maken hebben met een gegevensrij. Voor elke gegevensrij willen we naar het RadioButtonMarkup Literal-besturingselement programmatig verwijzen en de eigenschap Text instellen op de opmaak die moet worden verzonden. Zoals in de volgende code wordt weergegeven, wordt met de gegenereerde markering een keuzerondje gemaakt waarvan het name-kenmerk is ingesteld op SuppliersGroup, het id-kenmerk is ingesteld op RowSelectorX, waarbij X de index van de GridView-rij is, en waarvan het value-kenmerk is ingesteld op de index van de GridView-rij.

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);
    }
}

Wanneer een GridView-rij is geselecteerd en er een postback plaatsvindt, zijn we geïnteresseerd in de SupplierID van de geselecteerde leverancier. Daarom zou men kunnen denken dat de waarde van elke radioknop de eigenlijke SupplierID waarde zou moeten zijn (in plaats van de index van de GridView-rij). Hoewel dit in bepaalde omstandigheden kan werken, zou het een beveiligingsrisico zijn om blindelings een SupplierID te accepteren en verwerken. Onze GridView geeft bijvoorbeeld alleen die leveranciers in de VS weer. Als het SupplierID echter rechtstreeks wordt doorgegeven, wat verhindert dan dat een ondeugende gebruiker de SupplierID-waarde die op de postback wordt teruggestuurd, manipuleert? Door de rijindex als de value te gebruiken en vervolgens tijdens de postback de SupplierID uit de DataKeys verzameling op te halen, kunnen we ervoor zorgen dat de gebruiker slechts één van de SupplierID waarden gebruikt die gekoppeld zijn aan een van de GridView-rijen.

Nadat u deze gebeurtenishandlercode hebt toegevoegd, neemt u een minuut de tijd om de pagina in een browser te testen. Merk eerst op dat slechts één keuzerondje in het raster tegelijk kan worden geselecteerd. Wanneer u een keuzerondje selecteert en op een van de knoppen klikt, treedt er een postback op en worden de keuzerondjes allemaal teruggezet naar hun oorspronkelijke staat. Oftewel, bij een postback is het geselecteerde keuzerondje niet meer geselecteerd. Om dit op te lossen, moeten we de RowCreated gebeurtenishandler uitbreiden, zodat hij de geselecteerde radio button index die vanuit de postback wordt verzonden, controleert en het checked="checked" kenmerk toevoegt aan de gegenereerde markup van de rijen waarvan de index overeenkomt.

Wanneer een postback plaatsvindt, stuurt de browser de name en value van het geselecteerde keuzerondje terug. De waarde kan programmatisch worden opgehaald met behulp van Request.Form["name"]. De Request.Form eigenschap biedt een NameValueCollection weergave van de formuliervariabelen. De formuliervariabelen zijn de namen en waarden van de formuliervelden op de webpagina en worden door de webbrowser teruggestuurd wanneer een postback plaatsvindt. Omdat het gerenderde name kenmerk van de keuzerondjes in de GridView SuppliersGroup is, zal de browser SuppliersGroup=valueOfSelectedRadioButton terugsturen naar de webserver (samen met de andere formuliervelden) wanneer de webpagina wordt teruggestuurd. Deze informatie kan vervolgens worden geopend vanuit de Request.Form eigenschap met behulp van: Request.Form["SuppliersGroup"].

Omdat we de geselecteerde radioknopindex niet alleen moeten bepalen in de RowCreated gebeurtenis-handler, maar ook in de gebeurtenis-handlers voor de Webknoppen, voegen we een Click eigenschap toe aan de code-behind-klasse die SuppliersSelectedIndex teruggeeft wanneer er geen radioknop is geselecteerd, en de geselecteerde index als een van de radioknoppen is geselecteerd.

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

Als deze eigenschap is toegevoegd, weten we dat we de checked="checked" markup in de RowCreated event handler moeten toevoegen wanneer SuppliersSelectedIndex gelijk is aan e.Row.RowIndex. Werk de gebeurtenis-handler bij om deze logica op te nemen:

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 += " />";
    }
}

Met deze wijziging blijft de geselecteerde radioknop geselecteerd na een postback. Nu we de mogelijkheid hebben om op te geven welk keuzerondje is geselecteerd, kunnen we het gedrag wijzigen zodat wanneer de pagina voor het eerst werd bezocht, het keuzerondje van de eerste GridView-rij is geselecteerd (in plaats van dat er standaard geen keuzerondjes zijn geselecteerd, wat het huidige gedrag is). Als u het eerste keuzerondje standaard wilt laten selecteren, wijzigt u de if (SuppliersSelectedIndex == e.Row.RowIndex) instructie in het volgende: if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0))

Op dit moment hebben we een kolom met gegroepeerde selectievakjes toegevoegd aan de GridView, waarmee één rij in de GridView kan worden geselecteerd en onthouden bij het navigeren tussen postbacks. De volgende stappen zijn het weergeven van de producten van de geselecteerde leverancier. In stap 4 ziet u hoe u de gebruiker omleidt naar een andere pagina, waarbij de geselecteerde SupplierID wordt meegezonden. In stap 5 ziet u hoe u de producten van de geselecteerde leveranciers op dezelfde pagina in een GridView kunt weergeven.

Opmerking

In plaats van een TemplateField te gebruiken (de focus van deze lange stap 3), kunnen we een aangepaste DataControlField klasse maken die de juiste gebruikersinterface en functionaliteit weergeeft. De DataControlField klasse is de basisklasse waaruit de velden BoundField, CheckBoxField, TemplateField en andere ingebouwde GridView- en DetailsView-velden zijn afgeleid. Het maken van een aangepaste DataControlField klasse betekent dat de kolom met keuzerondjes kan worden toegevoegd met behulp van declaratieve syntaxis, en dat het repliceren van de functionaliteit op andere webpagina's en andere webtoepassingen aanzienlijk eenvoudiger zou maken.

Als u ooit aangepaste, gecompileerde besturingselementen in ASP.NET hebt gemaakt, weet u echter dat hiervoor een behoorlijke hoeveelheid beenwerk is vereist en een groot aantal subtiliteiten en randcases bevat die zorgvuldig moeten worden afgehandeld. Daarom zullen we voorlopig afzien van het implementeren van een kolom met keuzerondjes als een aangepaste DataControlField-klasse en blijven we bij de optie TemplateField. Misschien hebben we de kans om aangepaste DataControlField klassen te maken, te gebruiken en te implementeren in een toekomstige zelfstudie.

Stap 4: de producten van de geselecteerde leverancier weergeven op een afzonderlijke pagina

Nadat de gebruiker een GridView-rij heeft geselecteerd, moeten we de geselecteerde leveranciersproducten weergeven. In sommige gevallen willen we deze producten mogelijk op een afzonderlijke pagina weergeven, in andere kunnen we het liever op dezelfde pagina doen. Laten we eerst eens kijken hoe de producten op een afzonderlijke pagina worden weergegeven; in stap 5 kijken we naar het toevoegen van een GridView om de geselecteerde leveranciersproducten weer te RadioButtonField.aspx geven.

Er zijn momenteel twee knopwebbesturingselementen op de pagina ListProducts en SendToProducts. Wanneer op de SendToProducts knop wordt geklikt, willen we de gebruiker naartoe ~/Filtering/ProductsForSupplierDetails.aspxsturen. Deze pagina is gemaakt in de zelfstudie Master/Detail Filtering over twee pagina's en geeft de producten weer voor de leverancier waarvan SupplierID het querytekenreeksveld met de naam SupplierIDwordt doorgegeven.

Als u deze functionaliteit wilt bieden, maakt u een gebeurtenis-handler voor de SendToProducts Knop-Click gebeurtenis. In stap 3 hebben we de SuppliersSelectedIndex eigenschap toegevoegd, die de index retourneert van de rij waarvan het selectievakje is geselecteerd. De bijbehorende SupplierID kan worden opgehaald uit de GridView's collectie DataKeys en de gebruiker kan vervolgens worden verzonden naar ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierIDResponse.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);
    }
}

Deze code werkt prachtig zolang een van de radioknoppen is geselecteerd uit de GridView. Als in eerste instantie geen keuzerondjes voor GridView zijn geselecteerd en de gebruiker op de SendToProducts knop klikt, zal SuppliersSelectedIndex-1 zijn, wat een uitzondering veroorzaakt omdat -1 buiten het indexbereik van de DataKeys verzameling valt. Dit is echter geen probleem als u besluit de RowCreated gebeurtenissenhandler bij te werken zoals besproken in stap 3, zodat het eerste keuzerondje in de GridView aanvankelijk is geselecteerd.

Voeg een labelwebbesturingselement toe aan de pagina boven de GridView om plaats te bieden aan een SuppliersSelectedIndex waarde van -1. Stel de ID eigenschap in op ChooseSupplierMsg, stel de CssClass eigenschap in op Warning, stel de EnableViewState en Visible eigenschappen in op false, en stel de Text eigenschap in op Selecteer een leverancier uit de tabel. De CSS-klasse Warning geeft tekst weer in een rood, cursief, vet, groot lettertype en is gedefinieerd in Styles.css. Door de eigenschappen EnableViewState en Visible in te falsestellen, wordt het label alleen weergegeven bij die postbacks waarbij de eigenschap Visible van het besturingselement programmatisch is ingesteld op true.

Een labelwebbesturingselement toevoegen boven de GridView

Afbeelding 13: Een labelwebbesturingselement toevoegen boven de rasterweergave (klik om de afbeelding volledig weer te geven)

Vervolgens de Click gebeurtenis-handler uitbreiden om het ChooseSupplierMsg label weer te geven als SuppliersSelectedIndex kleiner is dan nul, en anders de gebruiker omleiden naar ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID.

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);
    }
}

Ga naar de pagina in een browser en klik op de SendToProducts knop voordat u een leverancier selecteert in de GridView. Zoals in afbeelding 14 wordt weergegeven, wordt het ChooseSupplierMsg label weergegeven. Selecteer vervolgens een leverancier en klik op de SendToProducts knop. Hiermee gaat u naar een pagina met de producten die door de geselecteerde leverancier worden geleverd. Afbeelding 15 toont de ProductsForSupplierDetails.aspx pagina wanneer de leverancier van bigfootbrouwerijen is geselecteerd.

Het label ChooseSupplierMsg wordt weergegeven als er geen leverancier is geselecteerd

Afbeelding 14: Het ChooseSupplierMsg label wordt weergegeven als er geen leverancier is geselecteerd (klik om de afbeelding op volledige grootte weer te geven)

De producten van de geselecteerde leverancier worden weergegeven in ProductsForSupplierDetails.aspx

Afbeelding 15: De producten van de geselecteerde leverancier worden weergegeven in ProductsForSupplierDetails.aspx (klik om de afbeelding op volledige grootte weer te geven)

Stap 5: de producten van de geselecteerde leverancier weergeven op dezelfde pagina

In stap 4 hebben we gezien hoe de gebruiker naar een andere webpagina wordt verzonden om de geselecteerde leveranciersproducten weer te geven. De geselecteerde leveranciersproducten kunnen ook op dezelfde pagina worden weergegeven. Ter illustratie voegen we nog een GridView toe aan RadioButtonField.aspx om de producten van de geselecteerde leverancier weer te geven.

Aangezien we alleen willen dat deze GridView van producten wordt weergegeven zodra een leverancier is geselecteerd, voegt u een Paneel Webcontrole toe onder de Suppliers GridView, stelt u de eigenschap ID in op ProductsBySupplierPanel en stelt u de eigenschap Visible in op false. Voeg in het deelvenster de tekst Producten voor de geselecteerde leverancier toe, gevolgd door een GridView met de naam ProductsBySupplier. Kies in de slimme tag van de GridView om het te koppelen aan een nieuwe ObjectDataSource genaamd ProductsBySupplierDataSource.

De ProductsBySupplier GridView verbinden met een nieuwe ObjectDataSource

Afbeelding 16: De ProductsBySupplier GridView binden aan een nieuwe ObjectDataSource (klik om de afbeelding op volledige grootte weer te geven)

Configureer vervolgens de ObjectDataSource om de ProductsBLL klasse te gebruiken. Omdat we alleen deze producten willen ophalen die door de geselecteerde leverancier worden geleverd, geeft u op dat de ObjectDataSource de methode moet aanroepen om de GetProductsBySupplierID(supplierID) gegevens op te halen. Selecteer (Geen) in de vervolgkeuzelijsten op de tabbladen UPDATE, INSERT en DELETE.

De ObjectDataSource configureren voor het gebruik van de methode GetProductsBySupplierID (supplierID)

Afbeelding 17: De ObjectDataSource configureren om de GetProductsBySupplierID(supplierID) methode te gebruiken (klik om de afbeelding op volledige grootte weer te geven)

De Drop-Down-lijsten instellen op (geen) in de tabbladen UPDATE, INSERT en DELETE

Afbeelding 18: Stel de Drop-Down-lijsten in op (Geen) in de tabbladen UPDATE, INSERT en DELETE (klik om de volledige afbeelding weer te geven)

Nadat u de tabbladen SELECT, UPDATE, INSERT en DELETE hebt geconfigureerd, klikt u op Volgende. Omdat bij de GetProductsBySupplierID(supplierID) methode een invoerparameter wordt verwacht, wordt in de wizard Gegevensbron maken gevraagd om de bron voor de parameterwaarde op te geven.

We hebben hier een aantal opties voor het opgeven van de bron van de parameterwaarde. We kunnen het standaardparameterobject gebruiken en de waarde van de SuppliersSelectedIndex eigenschap programmatisch toewijzen aan de eigenschap Parameter s DefaultValue in de gebeurtenis-handler van Selecting ObjectDataSource. Raadpleeg de zelfstudie Parameterwaarden van ObjectDataSource programmatisch instellen voor een opfrissing over het programmatisch toewijzen van waarden aan de parameters van de ObjectDataSource.

U kunt ook een ControlParameter gebruiken en verwijzen naar de Suppliers eigenschap GridView SelectedValue (zie afbeelding 19). De eigenschap GridView SelectedValue retourneert de DataKey waarde die overeenkomt met de SelectedIndex eigenschap. Om deze optie te laten werken, moeten we de eigenschap GridView SelectedIndex programmatisch instellen op de geselecteerde rij wanneer op de ListProducts knop wordt geklikt. Als extra voordeel, door de SelectedIndexgeselecteerde record in te stellen, neemt de geselecteerde record de SelectedRowStyle gedefinieerde in het DataWebControls thema (een gele achtergrond) over.

Een ControlParameter gebruiken om de GridView s SelectedValue op te geven als parameterbron

Afbeelding 19: Gebruik een ControlParameter om de GridView s SelectedValue op te geven als parameterbron (klik om de volledige afbeelding weer te geven)

Wanneer u de wizard hebt voltooid, worden in Visual Studio automatisch velden toegevoegd voor de gegevensvelden van het product. Verwijder alle, behalve de ProductName, CategoryNameen UnitPrice BoundFields en wijzig de HeaderText eigenschappen in Product, Categorie en Prijs. Configureer het BoundField zodanig dat de UnitPrice waarde wordt opgemaakt als een valuta. Nadat u deze wijzigingen hebt aangebracht, moeten de declaratieve markeringen van Panel, GridView en ObjectDataSource er als volgt uitzien:

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

Om deze oefening te voltooien, moeten we de eigenschap SelectedIndex van de GridView instellen op SelectedSuppliersIndex en de eigenschap ProductsBySupplierPanel van het Visible Paneel instellen op true wanneer op de ListProducts knop wordt geklikt. Hiervoor maakt u een eventhandler voor de ListProducts Button-Webcontrole Click gebeurtenis en voegt u de volgende code toe:

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;
    }
}

Als er geen leverancier is geselecteerd in GridView, wordt het ChooseSupplierMsg label weergegeven en wordt het ProductsBySupplierPanel deelvenster verborgen. Anders, als een leverancier is geselecteerd, wordt deze ProductsBySupplierPanel weergegeven en wordt de eigenschap van GridView SelectedIndex bijgewerkt.

In afbeelding 20 ziet u de resultaten nadat de leverancier bigfootbrouwerijen is geselecteerd en op de knop Producten op pagina weergeven is geklikt.

De producten geleverd door Bigfoot Breweries worden vermeld op dezelfde pagina

Afbeelding 20: De producten geleverd door Bigfoot Breweries worden weergegeven op dezelfde pagina (klik om de volledige afbeelding weer te geven)

Samenvatting

Zoals besproken in de Master/Detail Using a Selectable Master GridView with a Details DetailView tutorial, kunnen records worden geselecteerd uit een GridView met behulp van een CommandField waarvan de ShowSelectButton eigenschap is ingesteld op true. Maar het CommandField geeft de knoppen weer als gewone drukknoppen, koppelingen of afbeeldingen. Een alternatieve gebruikersinterface voor rijselectie is het opgeven van een keuzerondje of selectievakje in elke GridView-rij. In deze handleiding hebben we onderzocht hoe we een kolom met keuzerondjes kunnen toevoegen.

Helaas is het toevoegen van een kolom met keuzerondjes niet zo eenvoudig of simpel als je zou verwachten. Er is geen ingebouwd RadioButtonField dat kan worden toegevoegd met een klik op een knop en het gebruik van het besturingselement RadioButton Web in een TemplateField introduceert een eigen set problemen. Uiteindelijk moeten we een aangepaste DataControlField klasse maken of wijken we uit naar het injecteren van de juiste HTML in een TemplateField tijdens het RowCreated event om een dergelijke interface te bieden.

Nu we hebben verkend hoe we een kolom met keuzerondjes kunnen toevoegen, laten we ons richten op het toevoegen van een kolom met selectievakjes. Met een kolom met selectievakjes kan een gebruiker een of meer GridView-rijen selecteren en vervolgens een bewerking uitvoeren op alle geselecteerde rijen (zoals het selecteren van een set e-mailberichten van een web-e-mailclient en vervolgens alle geselecteerde e-mailberichten verwijderen). In de volgende zelfstudie ziet u hoe u een dergelijke kolom toevoegt.

Veel plezier met programmeren!

Over de auteur

Scott Mitchell, auteur van zeven ASP/ASP.NET-boeken en oprichter van 4GuysFromRolla.com, werkt sinds 1998 met Microsoft-webtechnologieën. Scott werkt als onafhankelijk consultant, trainer en schrijver. Zijn laatste boek is Sams Teach Yourself ASP.NET 2.0 in 24 uur. Hij kan worden bereikt op mitchell@4GuysFromRolla.com.

Speciale dank aan

Deze tutorialreeks is beoordeeld door veel behulpzame beoordelers. Hoofdrecensent voor deze tutorial was David Suru. Bent u geïnteresseerd in het bekijken van mijn aanstaande MSDN-artikelen? Zo ja, laat iets van je horen via mitchell@4GuysFromRolla.com.