Ajout d’une colonne GridView de cases d’option (C#)
par Scott Mitchell
Ce tutoriel explique comment ajouter une colonne de cases d’option à un contrôle GridView pour fournir à l’utilisateur un moyen plus intuitif de sélectionner une seule ligne de GridView.
Introduction
Le contrôle GridView offre de nombreuses fonctionnalités intégrées. Il comprend un certain nombre de champs différents pour afficher du texte, des images, des liens hypertexte et des boutons. Il prend en charge les modèles pour une personnalisation supplémentaire. En quelques clics de la souris, il est possible de créer un GridView dans lequel chaque ligne peut être sélectionnée via un bouton, ou d’activer les fonctionnalités de modification ou de suppression. Malgré la pléthore de fonctionnalités fournies, il arrive souvent que des fonctionnalités supplémentaires non prises en charge soient ajoutées. Dans ce tutoriel et les deux suivants, nous allons examiner comment améliorer les fonctionnalités de GridView pour inclure des fonctionnalités supplémentaires.
Ce tutoriel et le suivant se concentrent sur l’amélioration du processus de sélection de lignes. Comme nous l’avons examiné dans Master /Detail À l’aide d’un GridView maître sélectionnable avec un Details DetailView, nous pouvons ajouter un Champ de commandes au GridView qui comprend un bouton Sélectionner. Lorsque vous cliquez dessus, une publication s’ensuit et la propriété GridView est SelectedIndex
mise à jour vers l’index de la ligne dont le bouton Sélectionner a été cliqué. Dans le didacticiel Master/Detail Using a Selectable Master GridView with a DetailsView , nous avons vu comment utiliser cette fonctionnalité pour afficher les détails de la ligne GridView sélectionnée.
Bien que le bouton Sélectionner fonctionne dans de nombreuses situations, il peut ne pas fonctionner aussi bien pour d’autres personnes. Au lieu d’utiliser un bouton, deux autres éléments d’interface utilisateur sont couramment utilisés pour la sélection : la case d’option et la case à cocher. Nous pouvons augmenter le GridView afin qu’au lieu d’un bouton Sélectionner, chaque ligne contienne une case d’option ou une case à cocher. Dans les scénarios où l’utilisateur ne peut sélectionner qu’un seul des enregistrements GridView, la case d’option peut être préférée au bouton Sélectionner. Dans les situations où l’utilisateur peut potentiellement sélectionner plusieurs enregistrements, par exemple dans une application de messagerie web, où un utilisateur peut souhaiter sélectionner plusieurs messages pour supprimer la case à cocher offre des fonctionnalités qui ne sont pas disponibles à partir du bouton Sélectionner ou des interfaces utilisateur de case d’option.
Ce tutoriel explique comment ajouter une colonne de cases d’option à GridView. Le tutoriel suivant explore l’utilisation de cases à cocher.
Étape 1 : Création des pages web GridView
Avant de commencer à améliorer GridView pour inclure une colonne de cases d’option, prenons d’abord un moment pour créer les ASP.NET pages de notre projet de site web dont nous aurons besoin pour ce tutoriel et les deux suivants. Commencez par ajouter un nouveau dossier nommé EnhancedGridView
. Ensuite, ajoutez les pages ASP.NET suivantes à ce dossier, en veillant à associer chaque page à la Site.master
page master :
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
Figure 1 : Ajouter les pages ASP.NET pour les didacticiels SqlDataSource-Related
Comme dans les autres dossiers, Default.aspx
dans le EnhancedGridView
dossier répertoriera les tutoriels dans sa section. Rappelez-vous que le SectionLevelTutorialListing.ascx
contrôle utilisateur fournit cette fonctionnalité. Par conséquent, ajoutez ce contrôle utilisateur à Default.aspx
en le faisant glisser du Explorateur de solutions vers le mode Création de la page.
Figure 2 : Ajouter le SectionLevelTutorialListing.ascx
contrôle utilisateur à Default.aspx
(Cliquer pour afficher l’image en taille réelle)
Enfin, ajoutez ces quatre pages en tant qu’entrées au Web.sitemap
fichier. Plus précisément, ajoutez le balisage suivant après l’utilisation du contrôle <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>
Après la mise à jour Web.sitemap
, prenez un moment pour afficher le site web des tutoriels via un navigateur. Le menu de gauche inclut désormais des éléments pour la modification, l’insertion et la suppression des didacticiels.
Figure 3 : Le plan de site inclut désormais des entrées pour l’amélioration des didacticiels GridView
Étape 2 : Affichage des fournisseurs dans un GridView
Pour ce tutoriel, nous allons créer un GridView qui répertorie les fournisseurs des États-Unis, chaque ligne GridView fournissant une case d’option. Après avoir sélectionné un fournisseur via la case d’option, l’utilisateur peut afficher les produits du fournisseur en cliquant sur un bouton. Bien que cette tâche puisse sembler triviale, il existe un certain nombre de subtilités qui la rendent particulièrement délicate. Avant de nous pencher sur ces subtilités, nous allons d’abord obtenir un GridView répertoriant les fournisseurs.
Commencez par ouvrir la RadioButtonField.aspx
page dans le EnhancedGridView
dossier en faisant glisser un GridView de la boîte à outils vers le Designer. Définissez GridView sur ID
Suppliers
et, à partir de sa balise active, choisissez de créer une source de données. Plus précisément, créez un ObjectDataSource nommé SuppliersDataSource
qui extrait ses données de l’objet SuppliersBLL
.
Figure 4 : Créer un objetDataSource nommé SuppliersDataSource
(cliquer pour afficher l’image en taille réelle)
Figure 5 : Configurer ObjectDataSource pour utiliser la SuppliersBLL
classe (cliquer pour afficher l’image en taille réelle)
Étant donné que nous voulons uniquement répertorier ces fournisseurs aux États-Unis, choisissez la GetSuppliersByCountry(country)
méthode dans la liste déroulante de l’onglet SELECT.
Figure 6 : Configurer ObjectDataSource pour utiliser la SuppliersBLL
classe (cliquer pour afficher l’image en taille réelle)
Sous l’onglet UPDATE, sélectionnez l’option (Aucun), puis cliquez sur Suivant.
Figure 7 : Configurer ObjectDataSource pour utiliser la SuppliersBLL
classe (cliquer pour afficher l’image en taille réelle)
Étant donné que la GetSuppliersByCountry(country)
méthode accepte un paramètre, l’Assistant Configurer la source de données nous invite à entrer la source de ce paramètre. Pour spécifier une valeur codée en dur (USA, dans cet exemple), laissez la liste déroulante Source du paramètre définie sur Aucun et entrez la valeur par défaut dans la zone de texte. Cliquez sur Terminer pour terminer l'Assistant.
Figure 8 : Utiliser USA comme valeur par défaut pour le country
paramètre (cliquer pour afficher l’image en taille réelle)
Une fois l’Assistant terminé, GridView inclut un objet BoundField pour chacun des champs de données du fournisseur. Supprimez tous les CompanyName
éléments sauf , City
et Country
BoundFields, et renommez la CompanyName
propriété BoundFields HeaderText
en Fournisseur. Après cela, la syntaxe déclarative GridView et ObjectDataSource doit ressembler à ce qui suit.
<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>
Pour ce tutoriel, permettez à l’utilisateur d’afficher les produits des fournisseurs sélectionnés sur la même page que la liste des fournisseurs, ou sur une autre page. Pour ce faire, ajoutez deux contrôles Button Web à la page. J’ai défini les ID
s de ces deux boutons sur ListProducts
et SendToProducts
, avec l’idée que quand ListProducts
est cliqué une publication se produira et les produits du fournisseur sélectionné seront répertoriés sur la même page, mais quand SendToProducts
est cliqué, l’utilisateur sera redirigé vers une autre page qui répertorie les produits.
La figure 9 montre les Suppliers
contrôles GridView et les deux contrôles Web Button lorsqu’ils sont consultés via un navigateur.
Figure 9 : Les fournisseurs des États-Unis ont leur nom, leur ville et leur pays répertoriés (cliquer pour afficher l’image en taille réelle)
Étape 3 : Ajout d’une colonne de cases d’option
À ce stade, le Suppliers
GridView a trois boundFields qui affichent le nom de l’entreprise, la ville et le pays de chaque fournisseur aux États-Unis. Il manque toujours une colonne de cases d’option, cependant. Malheureusement, le GridView n’inclut pas de RadioButtonField intégré, sinon nous pourrions simplement ajouter cela à la grille et être fait. Au lieu de cela, nous pouvons ajouter un TemplateField et configurer son ItemTemplate
pour afficher une case d’option, ce qui entraîne une case d’option pour chaque ligne GridView.
Initialement, nous pouvons supposer que l’interface utilisateur souhaitée peut être implémentée en ajoutant un contrôle Web RadioButton au ItemTemplate
d’un TemplateField. Bien que cela ajoute en effet une case d’option unique à chaque ligne du GridView, les cases d’option ne peuvent pas être regroupées et ne sont donc pas mutuellement exclusives. Autrement dit, un utilisateur final peut sélectionner plusieurs cases d’option simultanément à partir de GridView.
Même si l’utilisation d’un champ de modèles de contrôles Web RadioButton n’offre pas les fonctionnalités dont nous avons besoin, implémentons cette approche, car il est utile d’examiner pourquoi les cases d’option obtenues ne sont pas regroupées. Commencez par ajouter un TemplateField au GridView fournisseurs, ce qui en fait le champ le plus à gauche. Ensuite, à partir de la balise active gridView, cliquez sur le lien Modifier les modèles et faites glisser un contrôle Web RadioButton à partir de la boîte à outils vers templateField ( ItemTemplate
voir figure 10). Définissez la propriété RadioButton sur ID
et la GroupName
propriété sur SuppliersGroup
.RowSelector
Figure 10 : Ajouter un contrôle Web RadioButton à (ItemTemplate
Cliquer pour afficher l’image en taille réelle)
Après avoir effectué ces ajouts via le Designer, votre balisage GridView doit ressembler à ce qui suit :
<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 propriété RadioButton s GroupName
est utilisée pour regrouper une série de cases d’option. Tous les contrôles RadioButton ayant la même GroupName
valeur sont considérés comme groupés ; une seule case d’option peut être sélectionnée à partir d’un groupe à la fois. La GroupName
propriété spécifie la valeur de l’attribut s de la case d’option name
rendue. Le navigateur examine les attributs des name
cases d’option pour déterminer les regroupements de cases d’option.
Avec le contrôle RadioButton Web ajouté à , ItemTemplate
accédez à cette page via un navigateur et cliquez sur les cases d’option dans les lignes de la grille. Notez que les cases d’option ne sont pas regroupées, ce qui permet de sélectionner toutes les lignes, comme le montre la figure 11.
Figure 11 : Les cases d’option de GridView ne sont pas regroupées (cliquer pour afficher l’image en taille réelle)
La raison pour laquelle les cases d’option ne sont pas regroupées est que leurs attributs rendus name
sont différents, bien qu’ayant le même GroupName
paramètre de propriété. Pour voir ces différences, effectuez une vue/source à partir du navigateur et examinez le balisage de la case d’option :
<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" />
Notez que les name
attributs et id
ne sont pas les valeurs exactes spécifiées dans le Fenêtre Propriétés, mais sont ajoutés à un certain nombre d’autres ID
valeurs. Les valeurs supplémentaires ID
ajoutées à l’avant du rendu id
et name
des attributs sont les ID
s des cases d’option parent contrôle les GridViewRow
s ID
, les GridView s ID
, les contrôles content s ID
et web Form s ID
. Ces ID
valeurs sont ajoutées afin que chaque contrôle Web rendu dans GridView ait une valeur et name
uniqueid
.
Chaque contrôle rendu a besoin d’un contrôle différent name
, id
car c’est ainsi que le navigateur identifie de manière unique chaque contrôle côté client et comment il identifie au serveur web l’action ou la modification qui s’est produite lors de la publication. Par exemple, imaginez que nous voulions exécuter du code côté serveur chaque fois qu’un état de vérification de RadioButton a été modifié. Pour ce faire, nous pouvons définir la propriété RadioButton sur AutoPostBack
et créer un gestionnaire d’événements pour l’événementCheckChanged
.true
Toutefois, si le rendu name
et id
les valeurs de toutes les cases d’option étaient identiques, lors de la publication, nous n’avons pas pu déterminer sur quel radioButton spécifique a été cliqué.
En bref, nous ne pouvons pas créer une colonne de cases d’option dans un GridView à l’aide du contrôle Web RadioButton. Au lieu de cela, nous devons utiliser des techniques plutôt archaïques pour nous assurer que le balisage approprié est injecté dans chaque ligne GridView.
Notes
Comme le contrôle Web RadioButton, le contrôle HTML de case d’option, lorsqu’il est ajouté à un modèle, inclut l’attribut unique name
, ce qui permet de dissocier les cases d’option de la grille. Si vous n’êtes pas familiarisé avec les contrôles HTML, n’hésitez pas à ignorer cette note, car les contrôles HTML sont rarement utilisés, en particulier dans ASP.NET 2.0. Mais si vous souhaitez en savoir plus, consultez l’entrée de blog de K. Scott Allencontrôles web et contrôles HTML.
Utilisation d’un contrôle littéral pour injecter le balisage de case d’option
Pour regrouper correctement toutes les cases d’option dans GridView, nous devons injecter manuellement le balisage des cases d’option dans le ItemTemplate
. Chaque case d’option a besoin du même name
attribut, mais doit avoir un attribut unique id
(si nous voulons accéder à une case d’option via un script côté client). Une fois qu’un utilisateur sélectionne une case d’option et publie la page, le navigateur renvoie la valeur de l’attribut de la case d’option value
sélectionné. Par conséquent, chaque case d’option a besoin d’un attribut unique value
. Enfin, lors de la publication, nous devons nous assurer d’ajouter l’attribut checked
à la case d’option sélectionnée. Dans le cas contraire, une fois que l’utilisateur a fait une sélection et a retranscrit, les cases d’option retournent à leur état par défaut (toutes non sélectionnées).
Il existe deux approches qui peuvent être prises pour injecter un balisage de bas niveau dans un modèle. L’une consiste à effectuer un mélange de balisage et d’appels aux méthodes de mise en forme définies dans la classe code-behind. Cette technique a été décrite pour la première fois dans le didacticiel Utilisation de TemplateFields dans le contrôle GridView . Dans notre cas, cela peut ressembler à ceci :
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
Ici, GetUniqueRadioButton
et GetRadioButtonValue
seraient des méthodes définies dans la classe code-behind qui a retourné les valeurs appropriées id
et value
d’attribut pour chaque case d’option. Cette approche fonctionne bien pour l’affectation id
des attributs et value
, mais elle est limitée lorsque vous devez spécifier la valeur de l’attribut checked
, car la syntaxe de liaison de données n’est exécutée que lorsque les données sont liées pour la première fois à GridView. Par conséquent, si l’état d’affichage de GridView est activé, les méthodes de mise en forme se déclenchent uniquement lorsque la page est chargée pour la première fois (ou lorsque le GridView est explicitement redirigé vers la source de données), et par conséquent, la fonction qui définit l’attribut checked
n’est pas appelée lors de la publication. C’est un problème assez subtil et un peu au-delà de la portée de cet article, donc je vais le laisser à ceci. Toutefois, je vous encourage à essayer d’utiliser l’approche ci-dessus et à la travailler jusqu’au point où vous serez bloqué. Bien qu’un tel exercice ne vous rapproche pas d’une version opérationnelle, il vous aidera à mieux comprendre gridView et le cycle de vie de la liaison de données.
L’autre approche pour injecter un balisage personnalisé de bas niveau dans un modèle et l’approche que nous allons utiliser pour ce didacticiel consiste à ajouter un contrôle Littéral au modèle. Ensuite, dans le gestionnaire d’événements RowCreated
GridView, RowDataBound
le contrôle Literal peut être accessible par programmation et sa Text
propriété est définie sur le balisage à émettre.
Commencez par supprimer le RadioButton du TemplateField, ItemTemplate
en le remplaçant par un contrôle Literal. Définissez le contrôle Littéral s ID
sur RadioButtonMarkup
.
Figure 12 : Ajouter un contrôle littéral à (ItemTemplate
Cliquer pour afficher l’image en taille réelle)
Ensuite, créez un gestionnaire d’événements pour l’événement GridView RowCreated
. L’événement RowCreated
se déclenche une fois pour chaque ligne ajoutée, que les données soient ou non en cours de rebond dans GridView. Cela signifie que même sur une publication lorsque les données sont rechargées à partir de l’état d’affichage, l’événement RowCreated
se déclenche toujours et c’est la raison pour laquelle nous l’utilisons à la place de RowDataBound
(qui se déclenche uniquement lorsque les données sont explicitement liées au contrôle Web de données).
Dans ce gestionnaire d’événements, nous voulons uniquement continuer si nous traitons une ligne de données. Pour chaque ligne de données, nous voulons référencer par programmation le RadioButtonMarkup
contrôle Literal et définir sa Text
propriété sur le balisage à émettre. Comme le montre le code suivant, le balisage émis crée une case d’option dont name
l’attribut est défini sur SuppliersGroup
, dont id
l’attribut est défini sur RowSelectorX
, où X est l’index de la ligne GridView et dont value
l’attribut est défini sur l’index de la ligne 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);
}
}
Lorsqu’une ligne GridView est sélectionnée et qu’une publication se produit, nous nous intéressons au SupplierID
fournisseur sélectionné. Par conséquent, on peut penser que la valeur de chaque case d’option doit être la valeur réelle SupplierID
(plutôt que l’index de la ligne GridView). Bien que cela puisse fonctionner dans certaines circonstances, il serait risqué pour la sécurité d’accepter et de traiter aveuglément un SupplierID
. Notre GridView, par exemple, répertorie uniquement les fournisseurs aux États-Unis. Toutefois, si le SupplierID
est transmis directement à partir de la case d’option, qu’est-ce qui empêche un utilisateur malicieux de manipuler la SupplierID
valeur renvoyée lors de la publication ? En utilisant l’index de ligne comme value
, puis en obtenant le SupplierID
sur publication de la DataKeys
collection, nous pouvons nous assurer que l’utilisateur n’utilise qu’une des SupplierID
valeurs associées à l’une des lignes GridView.
Après avoir ajouté ce code de gestionnaire d’événements, prenez une minute pour tester la page dans un navigateur. Tout d’abord, notez qu’une seule case d’option dans la grille peut être sélectionnée à la fois. Toutefois, lorsque vous sélectionnez une case d’option et que vous cliquez sur l’un des boutons, une publication se produit et les cases d’option reviennent toutes à leur état initial (autrement dit, lors de la publication, la case d’option sélectionnée n’est plus sélectionnée). Pour résoudre ce problème, nous devons augmenter le RowCreated
gestionnaire d’événements afin qu’il inspecte l’index de case d’option sélectionné envoyé à partir de la publication et ajoute l’attribut checked="checked"
au balisage émis des correspondances d’index de ligne.
Lorsqu’une publication se produit, le navigateur renvoie et name
value
de la case d’option sélectionnée. La valeur peut être récupérée par programmation à l’aide de Request.Form["name"]
. La Request.Form
propriété fournit un NameValueCollection
représentant les variables de formulaire. Les variables de formulaire sont les noms et les valeurs des champs de formulaire dans la page web, et sont renvoyées par le navigateur web chaque fois qu’une publication est effectuée. Étant donné que l’attribut rendu name
des cases d’option dans GridView est SuppliersGroup
, lorsque la page web est publiée, le navigateur renvoie SuppliersGroup=valueOfSelectedRadioButton
au serveur web (avec les autres champs de formulaire). Ces informations sont ensuite accessibles à partir de la propriété à l’aide Request.Form
de : Request.Form["SuppliersGroup"]
.
Étant donné que nous devons déterminer l’index de case d’option sélectionné non seulement dans le RowCreated
gestionnaire d’événements, mais aussi dans les Click
gestionnaires d’événements pour les contrôles Button Web, nous allons ajouter une SuppliersSelectedIndex
propriété à la classe code-behind qui retourne -1
si aucune case d’option n’a été sélectionnée et l’index sélectionné si l’une des cases d’option est sélectionnée.
private int SuppliersSelectedIndex
{
get
{
if (string.IsNullOrEmpty(Request.Form["SuppliersGroup"]))
return -1;
else
return Convert.ToInt32(Request.Form["SuppliersGroup"]);
}
}
Une fois cette propriété ajoutée, nous savons e.Row.RowIndex
qu’il faut ajouter le checked="checked"
balisage dans le RowCreated
gestionnaire d’événements quand SuppliersSelectedIndex
est égal à . Mettez à jour le gestionnaire d’événements pour inclure cette logique :
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 += " />";
}
}
Avec cette modification, la case d’option sélectionnée reste sélectionnée après une publication. Maintenant que nous avons la possibilité de spécifier la case d’option sélectionnée, nous pouvons modifier le comportement afin que, lors de la première visite de la page, la première case d’option de ligne GridView ait été sélectionnée (au lieu d’avoir aucune case d’option sélectionnée par défaut, ce qui est le comportement actuel). Pour que la première case d’option soit sélectionnée par défaut, remplacez simplement l’instruction if (SuppliersSelectedIndex == e.Row.RowIndex)
par la valeur suivante : if (SuppliersSelectedIndex == e.Row.RowIndex || (!Page.IsPostBack && e.Row.RowIndex == 0))
.
À ce stade, nous avons ajouté une colonne de cases d’option groupées à GridView qui permet de sélectionner et de mémoriser une seule ligne GridView dans les publications. Les étapes suivantes sont d’afficher les produits fournis par le fournisseur sélectionné. À l’étape 4, nous allons voir comment rediriger l’utilisateur vers une autre page, en envoyant le long du sélectionné SupplierID
. À l’étape 5, nous verrons comment afficher les produits du fournisseur sélectionnés dans un GridView sur la même page.
Notes
Au lieu d’utiliser un TemplateField (le focus de cette longue étape 3), nous pourrions créer une classe personnalisée DataControlField
qui restitue l’interface utilisateur et les fonctionnalités appropriées. La DataControlField
classe est la classe de base à partir de laquelle dérivent les champs BoundField, CheckBoxField, TemplateField et autres champs GridView et DetailsView intégrés. La création d’une classe personnalisée DataControlField
signifie que la colonne de cases d’option peut être ajoutée simplement à l’aide de la syntaxe déclarative, et facilite considérablement la réplication des fonctionnalités sur d’autres pages web et d’autres applications web.
Si vous avez déjà créé des contrôles compilés personnalisés dans ASP.NET, toutefois, vous savez que cela nécessite une bonne quantité de travail et comporte une multitude de subtilités et de cas de bord qui doivent être gérés avec soin. Par conséquent, nous allons renoncer à implémenter une colonne de cases d’option en tant que classe personnalisée DataControlField
pour l’instant et nous nous en tenir à l’option TemplateField. Nous aurons peut-être la possibilité d’explorer la création, l’utilisation et le déploiement de classes personnalisées DataControlField
dans un prochain tutoriel !
Étape 4 : Affichage des produits du fournisseur sélectionnés dans une page distincte
Une fois que l’utilisateur a sélectionné une ligne GridView, nous devons afficher les produits du fournisseur sélectionnés. Dans certaines circonstances, nous pouvons souhaiter afficher ces produits dans une page distincte, dans d’autres, nous préférerons le faire dans la même page. Examinons d’abord comment afficher les produits dans une page distincte ; À l’étape 5, nous allons examiner l’ajout d’un GridView à RadioButtonField.aspx
pour afficher les produits du fournisseur sélectionné.
Il existe actuellement deux contrôles Button Web sur la page ListProducts
et SendToProducts
. Lorsque vous cliquez sur le SendToProducts
bouton, nous voulons envoyer l’utilisateur à ~/Filtering/ProductsForSupplierDetails.aspx
. Cette page a été créée dans le didacticiel Master/Detail Filtering Across Two Pages et affiche les produits du fournisseur dont SupplierID
le champ de chaîne de requête nommé SupplierID
.
Pour fournir cette fonctionnalité, créez un gestionnaire d’événements pour l’événement SendToProducts
Button.Click
À l’étape 3, nous avons ajouté la SuppliersSelectedIndex
propriété , qui retourne l’index de la ligne dont la case d’option est sélectionnée. Le correspondant SupplierID
peut être récupéré à partir de la collection GridView DataKeys
et l’utilisateur peut ensuite être envoyé à l’aide Response.Redirect("url")
de ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
.
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);
}
}
Ce code fonctionne parfaitement tant que l’une des cases d’option est sélectionnée dans GridView. Si, initialement, gridView n’a pas de cases d’option sélectionnées et que l’utilisateur clique sur le SendToProducts
bouton, SuppliersSelectedIndex
est -1
, ce qui entraîne la levée d’une exception, car -1
est en dehors de la plage d’index de la DataKeys
collection. Toutefois, ce n’est pas un problème si vous avez décidé de mettre à jour le RowCreated
gestionnaire d’événements comme indiqué à l’étape 3 afin que la première case d’option de GridView soit initialement sélectionnée.
Pour prendre en compte la SuppliersSelectedIndex
valeur -1
, ajoutez un contrôle Label Web à la page au-dessus de GridView. Définissez sa ID
propriété sur ChooseSupplierMsg
, sa CssClass
propriété sur Warning
, ses EnableViewState
propriétés false
et Visible
sur , et sa Text
propriété sur Veuillez choisir un fournisseur dans la grille. La classe Warning
CSS affiche le texte dans une police rouge, italique, gras et volumineuse et est définie dans Styles.css
. En définissant les EnableViewState
propriétés false
et Visible
sur , l’étiquette n’est pas rendue, sauf pour les publications postback où la propriété du Visible
contrôle est définie par programmation sur true
.
Figure 13 : Ajouter un contrôle Web Label au-dessus du GridView (cliquer pour afficher l’image en taille réelle)
Ensuite, augmentez le Click
gestionnaire d’événements pour afficher l’étiquette ChooseSupplierMsg
si SuppliersSelectedIndex
est inférieure à zéro et redirigez l’utilisateur vers ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
le cas contraire.
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);
}
}
Visitez la page dans un navigateur et cliquez sur le SendToProducts
bouton avant de sélectionner un fournisseur dans GridView. Comme le montre la figure 14, l’étiquette est ChooseSupplierMsg
affichée. Ensuite, sélectionnez un fournisseur, puis cliquez sur le SendToProducts
bouton . Vous accédez alors à une page qui répertorie les produits fournis par le fournisseur sélectionné. La figure 15 montre la ProductsForSupplierDetails.aspx
page où le fournisseur Bigfoot Breweries a été sélectionné.
Figure 14 : L’étiquette ChooseSupplierMsg
s’affiche si aucun fournisseur n’est sélectionné (Cliquez pour afficher l’image en taille réelle)
Figure 15 : Les produits du fournisseur sélectionnés sont affichés dans ProductsForSupplierDetails.aspx
(Cliquer pour afficher l’image en taille réelle)
Étape 5 : affichage des produits du fournisseur sélectionnés sur la même page
À l’étape 4, nous avons vu comment envoyer l’utilisateur à une autre page web pour afficher les produits du fournisseur sélectionné. Vous pouvez également afficher les produits du fournisseur sélectionnés sur la même page. Pour illustrer cela, nous allons ajouter un autre GridView à RadioButtonField.aspx
pour afficher les produits du fournisseur sélectionnés.
Étant donné que nous voulons que ce GridView de produits s’affiche uniquement une fois qu’un fournisseur a été sélectionné, ajoutez un contrôle Web panel sous le Suppliers
GridView, affectant à ProductsBySupplierPanel
et ID
à sa Visible
propriété la valeur false
. Dans le panneau, ajoutez le texte Products pour le fournisseur sélectionné, suivi d’un GridView nommé ProductsBySupplier
. À partir de la balise active GridView, choisissez de la lier à un nouvel ObjetDataSource nommé ProductsBySupplierDataSource
.
Figure 16 : Lier gridView ProductsBySupplier
à une nouvelle propriété ObjectDataSource (cliquer pour afficher une image de taille réelle)
Ensuite, configurez ObjectDataSource pour utiliser la ProductsBLL
classe . Étant donné que nous voulons uniquement récupérer les produits fournis par le fournisseur sélectionné, spécifiez que ObjectDataSource doit appeler la GetProductsBySupplierID(supplierID)
méthode pour récupérer ses données. Sélectionnez (Aucun) dans les listes déroulantes des onglets UPDATE, INSERT et DELETE.
Figure 17 : Configurer ObjectDataSource pour utiliser la GetProductsBySupplierID(supplierID)
méthode (Cliquer pour afficher l’image en taille réelle)
Figure 18 : Définissez le Drop-Down Listes sur (Aucun) dans les onglets UPDATE, INSERT et DELETE (Cliquer pour afficher l’image en taille réelle)
Après avoir configuré les onglets SELECT, UPDATE, INSERT et DELETE, cliquez sur Suivant. Étant donné que la GetProductsBySupplierID(supplierID)
méthode attend un paramètre d’entrée, l’Assistant Création d’une source de données nous invite à spécifier la source pour la valeur s du paramètre.
Nous disposons ici de quelques options pour spécifier la source de la valeur s du paramètre. Nous pouvons utiliser l’objet Parameter par défaut et affecter par programmation la valeur de la SuppliersSelectedIndex
propriété à la propriété Parameter s DefaultValue
dans le gestionnaire d’événements Selecting
ObjectDataSource. Reportez-vous au didacticiel Définition par programmation des valeurs de paramètres d’ObjectDataSource pour une actualisation sur l’affectation de valeurs par programmation aux paramètres d’ObjectDataSource.
Vous pouvez également utiliser un ControlParameter et faire référence à la Suppliers
propriété GridView SelectedValue
(voir figure 19). La propriété GridView renvoie SelectedValue
la DataKey
valeur correspondant à la SelectedIndex
propriété . Pour que cette option fonctionne, nous devons définir par programmation la propriété GridView SelectedIndex
sur la ligne sélectionnée lorsque vous cliquez sur le ListProducts
bouton. En outre, en définissant , SelectedIndex
l’enregistrement sélectionné prend le SelectedRowStyle
défini dans le DataWebControls
thème (arrière-plan jaune).
Figure 19 : Utiliser un ControlParameter pour spécifier le GridView s SelectedValue comme source de paramètre (cliquer pour afficher l’image en taille réelle)
À la fin de l’Assistant, Visual Studio ajoute automatiquement des champs pour les champs de données du produit. Supprimez tous les éléments sauf , ProductName
CategoryName
et UnitPrice
BoundFields, et remplacez les HeaderText
propriétés par Product, Category et Price. Configurez BoundField UnitPrice
pour que sa valeur soit mise en forme en tant que devise. Après avoir apporté ces modifications, le balisage déclaratif de Panel, GridView et ObjectDataSource doit ressembler à ce qui suit :
<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>
Pour effectuer cet exercice, nous devons définir la propriété GridView SelectedIndex
sur et la ProductsBySupplierPanel
SelectedSuppliersIndex
propriété Panel sur Visible
true
lorsque vous cliquez sur le ListProducts
bouton. Pour ce faire, créez un gestionnaire d’événements pour l’événement ListProducts
Button Web control s Click
et ajoutez le code suivant :
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;
}
}
Si un fournisseur n’a pas été sélectionné dans GridView, l’étiquette ChooseSupplierMsg
s’affiche et le ProductsBySupplierPanel
panneau masqué. Sinon, si un fournisseur a été sélectionné, le ProductsBySupplierPanel
s’affiche et la propriété GridView est SelectedIndex
mise à jour.
La figure 20 montre les résultats une fois que le fournisseur Bigfoot Breweries a été sélectionné et que le bouton Afficher les produits sur la page a été cliqué.
Figure 20 : Les produits fournis par Bigfoot Breweries sont répertoriés sur la même page (cliquez pour afficher l’image en taille réelle)
Résumé
Comme indiqué dans le tutoriel Master/Detail Using a Selectable Master GridView with a Details DetailView tutorial, les enregistrements peuvent être sélectionnés à partir d’un GridView à l’aide d’un CommandField dont ShowSelectButton
la propriété est définie sur true
. Mais le Champ de commande affiche ses boutons sous forme de boutons push standard, de liens ou d’images. Une autre interface utilisateur de sélection de lignes consiste à fournir une case d’option ou une case à cocher dans chaque ligne GridView. Dans ce tutoriel, nous avons examiné comment ajouter une colonne de cases d’option.
Malheureusement, l’ajout d’une colonne de cases d’option n’est pas aussi simple ou aussi simple que l’on pourrait s’y attendre. Il n’existe pas de RadioButtonField intégré qui peut être ajouté en un clic, et l’utilisation du contrôle Web RadioButton dans un TemplateField introduit son propre ensemble de problèmes. En fin de compte, pour fournir une telle interface, nous devons créer une classe personnalisée DataControlField
ou recourir à injecter le code HTML approprié dans un TemplateField pendant l’événement RowCreated
.
Après avoir exploré comment ajouter une colonne de cases d’option, nous allons nous intéresser à l’ajout d’une colonne de cases à cocher. Avec une colonne de cases à cocher, un utilisateur peut sélectionner une ou plusieurs lignes GridView, puis effectuer une opération sur toutes les lignes sélectionnées (par exemple, sélectionner un ensemble d’e-mails à partir d’un client de messagerie web, puis choisir de supprimer tous les e-mails sélectionnés). Dans le tutoriel suivant, nous allons voir comment ajouter une telle colonne.
Bonne programmation !
À propos de l’auteur
Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille comme consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 in 24 Heures. Il est accessible à l’adressemitchell@4GuysFromRolla.com . ou via son blog, qui peut être trouvé à l’adresse http://ScottOnWriting.NET.
Un merci spécial à
Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Le réviseur principal de ce tutoriel était David Suru. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.