Partager via


Insertion d’un nouvel enregistrement depuis le pied de page d’un GridView (C#)

par Scott Mitchell

Télécharger le PDF

Bien que le contrôle GridView ne fournit pas de prise en charge intégrée pour l’insertion d’un nouvel enregistrement de données, ce tutoriel montre comment augmenter GridView pour inclure une interface d’insertion.

Présentation

Comme indiqué dans le didacticiel Vue d’ensemble de l’insertion, de la mise à jour et de la suppression de données , les contrôles Web GridView, DetailsView et FormView incluent chacun des fonctionnalités de modification de données intégrées. Lorsqu’ils sont utilisés avec des contrôles de source de données déclaratifs, ces trois contrôles Web peuvent être rapidement et facilement configurés pour modifier des données, et dans des scénarios sans avoir à écrire une seule ligne de code. Malheureusement, seuls les contrôles DetailsView et FormView fournissent des fonctionnalités intégrées d’insertion, de modification et de suppression. GridView offre uniquement la prise en charge de la modification et de la suppression. Toutefois, avec une petite graisse de coude, nous pouvons augmenter le GridView pour inclure une interface d’insertion.

En ajoutant des fonctionnalités d’insertion à GridView, nous sommes chargés de décider de la façon dont de nouveaux enregistrements seront ajoutés, de créer l’interface d’insertion et d’écrire le code pour insérer le nouvel enregistrement. Dans ce tutoriel, nous allons examiner l’ajout de l’interface d’insertion à la ligne de pied de page de GridView (voir la figure 1). La cellule de pied de page de chaque colonne inclut l’élément d’interface utilisateur de collecte de données approprié (un TextBox pour le nom du produit, un DropDownList pour le fournisseur, etc.). Nous avons également besoin d’une colonne pour un bouton Ajouter qui, lorsqu’on clique dessus, entraîne un postback et insère un nouvel enregistrement dans la table Products à l’aide des valeurs fournies dans la ligne de pied de page.

La ligne pied de page fournit une interface permettant d’ajouter de nouveaux produits

Figure 1 : La ligne pied de page fournit une interface permettant d’ajouter de nouveaux produits (cliquez pour afficher l’image de taille complète)

Étape 1 : affichage des informations sur le produit dans un GridView

Avant de nous préoccuper de la création de l’interface d’insertion dans le pied de page de GridView, nous allons tout d’abord nous concentrer sur l’ajout d’un GridView à la page qui répertorie les produits de la base de données. Commencez par ouvrir la page InsertThroughFooter.aspx dans le dossier EnhancedGridView et faites glisser un GridView à partir de la boîte à outils sur le plan de conception, en définissant la propriété ID du GridView sur Products. Ensuite, utilisez la balise active gridView pour la lier à un nouvel ObjectDataSource nommé ProductsDataSource.

Créer un objet ObjectDataSource nommé ProductsDataSource

Figure 2 : Créer un ObjetDataSource nommé ProductsDataSource (cliquez pour afficher l’image de taille complète)

Configurez ObjectDataSource pour utiliser la méthode de la classe ProductsBLLGetProducts() pour récupérer les informations de produit. Pour ce didacticiel, nous allons nous concentrer strictement sur l’ajout de fonctionnalités d’insertion et ne pas vous soucier de la modification et de la suppression. Par conséquent, assurez-vous que la liste déroulante de l’onglet INSERT est définie AddProduct() sur et que les listes déroulantes des onglets UPDATE et DELETE sont définies sur (Aucun).

Mapper la méthode AddProduct à la méthode Insert() de l'ObjectDataSource

Figure 3 : Associer la AddProduct méthode à la méthode de l'ObjectDataSource Insert() (Cliquez pour afficher l’image de taille complète)

Définir les onglets « UPDATE » et « DELETE » de liste Drop-Down sur (Aucun)

Figure 4 : Définissez les onglets UPDATE et DELETE des listes Drop-Down sur (Aucun) (Cliquez pour afficher l'image en taille réelle)

Une fois l’assistant de configuration de la source de données ObjectDataSource terminé, Visual Studio ajoute automatiquement des champs à le GridView pour chacun des champs de données correspondants. Pour l’instant, laissez tous les champs ajoutés par Visual Studio. Plus loin dans ce tutoriel, nous allons revenir en arrière et supprimer certains des champs dont les valeurs n’ont pas besoin d’être spécifiées lors de l’ajout d’un nouvel enregistrement.

Étant donné qu’il existe près de 80 produits dans la base de données, un utilisateur devra faire défiler jusqu’au bas de la page web pour ajouter un nouvel enregistrement. Par conséquent, activez la pagination pour rendre l’interface d’insertion plus visible et accessible. Pour activer la pagination, cochez simplement la case Activer la pagination à partir de la balise intelligente de GridView.

À ce stade, le balisage déclaratif gridView et ObjectDataSource doit ressembler à ce qui suit :

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    AllowPaging="True" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID" 
            InsertVisible="False" ReadOnly="True" 
            SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="ProductName" 
            SortExpression="ProductName" />
        <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" 
            SortExpression="SupplierID" />
        <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" 
            SortExpression="CategoryID" />
        <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" 
            SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" 
            SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" 
            SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" 
            SortExpression="UnitsOnOrder" />
        <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel" 
            SortExpression="ReorderLevel" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" 
            SortExpression="Discontinued" />
        <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" 
            ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="SupplierName" 
            ReadOnly="True" SortExpression="SupplierName" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}" 
    SelectMethod="GetProducts" TypeName="ProductsBLL">
    <InsertParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="supplierID" Type="Int32" />
        <asp:Parameter Name="categoryID" Type="Int32" />
        <asp:Parameter Name="quantityPerUnit" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="unitsInStock" Type="Int16" />
        <asp:Parameter Name="unitsOnOrder" Type="Int16" />
        <asp:Parameter Name="reorderLevel" Type="Int16" />
        <asp:Parameter Name="discontinued" Type="Boolean" />
    </InsertParameters>
</asp:ObjectDataSource>

Tous les champs de données de produit sont affichés dans un GridView paginé

Figure 5 : Tous les champs de données de produit sont affichés dans une grille paginée (cliquez pour afficher l’image de taille complète)

Outre ses lignes d’en-tête et de données, GridView inclut une ligne de pied de page. Les lignes d’en-tête et de pied de page sont affichées en fonction des valeurs des propriétés de ShowHeader et ShowFooter du GridView. Pour afficher la ligne du pied de page, définissez simplement la propriété ShowFooter sur true. Comme l’illustre la figure 6, la définition de la propriété ShowFooter à true ajoute une ligne de pied de page à la grille.

Pour afficher la ligne pied de page, définissez ShowFooter sur True

Figure 6 : Pour afficher la ligne du pied de page, définissez ShowFooterTrue sur (Cliquez pour afficher l’image de taille complète)

Notez que la ligne de pied de page a une couleur d’arrière-plan rouge foncée. Cela est dû au thème DataWebControls que nous avons créé et appliqué à toutes les pages dans le didacticiel Displaying Data With the ObjectDataSource . Plus précisément, le GridView.skin fichier configure la FooterStyle propriété telle qu’elle utilise la FooterStyle classe CSS. La classe FooterStyle est définie dans Styles.css comme suit :

.FooterStyle
{
    background-color: #a33;
    color: White;
    text-align: right;
}

Remarque

Nous avons exploré l’utilisation de la ligne du pied de page GridView dans les didacticiels précédents. Si nécessaire, reportez-vous au didacticiel sur l’affichage des informations récapitulatives dans le pied de page de GridView pour un rappel.

Après avoir défini la propriété ShowFooter à true, prenez un moment pour afficher le résultat dans un navigateur. Actuellement, la ligne de pied de page ne contient aucun texte ou contrôle Web. À l’étape 3, nous allons modifier le pied de page pour chaque champ GridView afin qu’il inclut l’interface d’insertion appropriée.

La ligne de pied de page vide s’affiche au-dessus des contrôles d’interface de pagination

Figure 7 : La ligne de pied de page vide s’affiche au-dessus des contrôles d’interface de pagination (cliquez pour afficher l’image de taille complète)

De retour dans le didacticiel Utilisation de TemplateFields dans le didacticiel contrôle GridView , nous avons vu comment personnaliser considérablement l’affichage d’une colonne GridView particulière à l’aide de TemplateFields (par opposition à BoundFields ou CheckBoxFields) ; Dans la personnalisation de l’interface de modification de données , nous avons examiné l’utilisation de TemplateFields pour personnaliser l’interface d’édition dans un GridView. Rappelez-vous qu’un TemplateField est composé d’un certain nombre de modèles qui définissent la combinaison de balisage, de contrôles Web et de syntaxe de liaison de données utilisée pour certains types de lignes. Par exemple, ItemTemplate spécifie le modèle utilisé pour les lignes en lecture seule, tandis que EditItemTemplate définit le modèle pour la ligne modifiable.

En plus de ItemTemplate et EditItemTemplate, le TemplateField inclut également un FooterTemplate qui spécifie le contenu de la ligne de pied de page. Par conséquent, nous pouvons ajouter les contrôles Web nécessaires pour chaque interface d’insertion de champ dans le FooterTemplate. Pour commencer, convertissez tous les champs de GridView en TemplateFields. Pour ce faire, cliquez sur le lien Modifier les colonnes dans la balise active gridView, en sélectionnant chaque champ dans le coin inférieur gauche, puis en cliquant sur le lien Convertir ce champ dans un lien TemplateField.

Convertir chaque champ en un templateField

Figure 8 : Convertir chaque champ en champ de modèle

Le fait de cliquer sur Convertir ce champ en modèleField transforme le type de champ actuel en un champ TemplateField équivalent. Par exemple, chaque BoundField est remplacé par un TemplateField avec un ItemTemplate Label qui affiche le champ de données correspondant et un EditItemTemplate qui affiche le champ de données dans une TextBox. BoundField ProductName a été converti en balisage TemplateField suivant :

<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
    <EditItemTemplate>
        <asp:TextBox ID="TextBox1" runat="server" 
            Text='<%# Bind("ProductName") %>'></asp:TextBox>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Label ID="Label2" runat="server" 
            Text='<%# Bind("ProductName") %>'></asp:Label>
    </ItemTemplate>
</asp:TemplateField>

De même, le Discontinued CheckBoxField a été converti en TemplateField dont le ItemTemplate et EditItemTemplate contiennent un contrôle Web CheckBox (avec la case à cocher du ItemTemplate CheckBox désactivée). L’objet BoundField en lecture seule ProductID a été converti en modèleField avec un contrôle Label à la fois dans l’objet ItemTemplate et EditItemTemplate. En bref, la conversion d’un champ GridView existant en un TemplateField est un moyen rapide et facile de basculer vers le ModèleField plus personnalisable sans perdre les fonctionnalités existantes du champ.

Étant donné que le GridView avec lequel nous travaillons ne prend pas en charge la modification, n’hésitez pas à supprimer le EditItemTemplate de chaque TemplateField, en laissant uniquement le ItemTemplate. Après cela, le balisage déclaratif de GridView doit ressembler à ce qui suit :

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    AllowPaging="True" EnableViewState="False" ShowFooter="True">
    <Columns>
        <asp:TemplateField HeaderText="ProductID" InsertVisible="False" 
            SortExpression="ProductID">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" 
                    Text='<%# Bind("ProductID") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" 
                    Text='<%# Bind("ProductName") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="SupplierID" SortExpression="SupplierID">
            <ItemTemplate>
                <asp:Label ID="Label3" runat="server" 
                    Text='<%# Bind("SupplierID") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="CategoryID" SortExpression="CategoryID">
            <ItemTemplate>
                <asp:Label ID="Label4" runat="server" 
                    Text='<%# Bind("CategoryID") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="QuantityPerUnit" 
            SortExpression="QuantityPerUnit">
            <ItemTemplate>
                <asp:Label ID="Label5" runat="server" 
                    Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="UnitPrice" SortExpression="UnitPrice">
            <ItemTemplate>
                <asp:Label ID="Label6" runat="server" 
                    Text='<%# Bind("UnitPrice") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="UnitsInStock" 
            SortExpression="UnitsInStock">
            <ItemTemplate>
                <asp:Label ID="Label7" runat="server" 
                    Text='<%# Bind("UnitsInStock") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="UnitsOnOrder" 
            SortExpression="UnitsOnOrder">
            <ItemTemplate>
                <asp:Label ID="Label8" runat="server" 
                    Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="ReorderLevel" 
            SortExpression="ReorderLevel">
            <ItemTemplate>
                <asp:Label ID="Label9" runat="server" 
                    Text='<%# Bind("ReorderLevel") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Discontinued" 
            SortExpression="Discontinued">
            <ItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server" 
                    Checked='<%# Bind("Discontinued") %>' Enabled="false" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="CategoryName" 
            SortExpression="CategoryName">
            <ItemTemplate>
                <asp:Label ID="Label10" runat="server" 
                    Text='<%# Bind("CategoryName") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="SupplierName" 
            SortExpression="SupplierName">
            <ItemTemplate>
                <asp:Label ID="Label11" runat="server" 
                    Text='<%# Bind("SupplierName") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Maintenant que chaque champ GridView a été converti en TemplateField, nous pouvons entrer l’interface d’insertion appropriée dans chaque champ de FooterTemplate. Certains champs n’auront pas d’interface d’insertion (ProductIDpar exemple), d’autres varient dans les contrôles Web utilisés pour collecter les informations du nouveau produit.

Pour créer l’interface d’édition, choisissez le lien Modifier les modèles à partir de la balise active gridView. Ensuite, dans la liste déroulante, sélectionnez les champs appropriés FooterTemplate et faites glisser le contrôle approprié de la boîte à outils vers le Concepteur.

Ajouter l’interface d’insertion appropriée à chaque modèle de pied de page de champ

Figure 9 : Ajouter l’interface d’insertion appropriée à chaque champ FooterTemplate (cliquez pour afficher l’image de taille complète)

La liste à puces suivante énumère les champs GridView, en spécifiant l’interface d’insertion à ajouter :

  • ProductID aucun.
  • ProductName ajoutez un TextBox et définissez sa propriété ID à NewProductName. Ajoutez également un contrôle RequiredFieldValidator pour vous assurer que l’utilisateur entre une valeur pour le nom du nouveau produit.
  • SupplierID aucun.
  • CategoryID aucun.
  • QuantityPerUnit ajoutez une zone de texte, en définissant sa ID sur NewQuantityPerUnit.
  • UnitPrice ajoutez un TextBox nommé NewUnitPrice et un CompareValidator qui garantit que la valeur entrée est une valeur monétaire supérieure ou égale à zéro.
  • UnitsInStock utilisez une zone de texte dont la valeur de ID est définie sur NewUnitsInStock. Incluez un CompareValidator qui garantit que la valeur entrée est une valeur entière supérieure ou égale à zéro.
  • UnitsOnOrder utilisez une zone de texte dont la valeur de ID est définie sur NewUnitsOnOrder. Incluez un CompareValidator qui garantit que la valeur entrée est une valeur entière supérieure ou égale à zéro.
  • ReorderLevel utilisez une zone de texte dont la valeur de ID est définie sur NewReorderLevel. Incluez un CompareValidator qui garantit que la valeur entrée est une valeur entière supérieure ou égale à zéro.
  • Discontinued ajoutez une case à cocher, en définissant son ID à NewDiscontinued.
  • CategoryName ajoutez un DropDownList et définissez-le ID sur NewCategoryID. Liez-le à un nouvel ObjectDataSource nommé CategoriesDataSource et configurez-le pour utiliser la méthode CategoriesBLL de la classe GetCategories(). Faites en sorte que les listes déroulantes ListItem affichent le champ de données CategoryName en utilisant le champ de données CategoryID comme valeurs.
  • SupplierName ajoutez un DropDownList et définissez-le ID sur NewSupplierID. Liez-le à un nouvel ObjectDataSource nommé SuppliersDataSource et configurez-le pour utiliser la méthode SuppliersBLL de la classe GetSuppliers(). Faites en sorte que les listes déroulantes ListItem affichent le champ de données CompanyName en utilisant le champ de données SupplierID comme valeurs.

Pour chacun des contrôles de validation, effacez la propriété afin que la couleur de premier plan blanche de la ForeColorFooterStyle classe CSS soit utilisée à la place du rouge par défaut. Utilisez également la ErrorMessage propriété pour une description détaillée, mais définissez la Text propriété sur un astérisque. Pour empêcher le texte du contrôle de validation de faire passer l'interface à deux lignes, définissez la propriété FooterStyleWrap sur false pour chaque FooterTemplate qui utilise un contrôle de validation. Enfin, ajoutez un contrôle ValidationSummary sous le GridView et définissez sa ShowMessageBox propriété sur true et sa ShowSummary propriété sur false.

Lors de l’ajout d’un nouveau produit, nous devons fournir le CategoryID et SupplierID. Ces informations sont capturées via les listes déroulantes des cellules du pied de page pour les champs CategoryName et SupplierName. J'ai choisi d'utiliser ces champs au lieu des champs TemplateFields pour les CategoryID et SupplierID, car dans les lignes de données de la grille, l'utilisateur est probablement plus intéressé par les noms des catégories et des fournisseurs plutôt que par leurs valeurs d'ID. Étant donné que les valeurs CategoryID et SupplierID sont désormais capturées dans les interfaces d’insertion des champs CategoryName et SupplierName, nous pouvons supprimer les TemplateFields CategoryID et SupplierID de la GridView.

De même, il ProductID n’est pas utilisé lors de l’ajout d’un nouveau produit, de sorte que ProductID TemplateField peut également être supprimé. Toutefois, laissez le ProductID champ dans la grille. En plus des contrôles TextBoxes, DropDownLists, CheckBoxes et validation qui composent l’interface d’insertion, nous aurons également besoin d’un bouton Ajouter qui, lorsque vous cliquez dessus, effectue la logique pour ajouter le nouveau produit à la base de données. À l’étape 4, nous allons inclure un bouton Ajouter dans l’interface d’insertion dans templateField ProductID s FooterTemplate.

N’hésitez pas à améliorer l’apparence des différents champs GridView. Par exemple, vous pouvez mettre en forme les valeurs UnitPrice en tant que devise, aligner à droite les champs UnitsInStock, UnitsOnOrder, et ReorderLevel, et mettre à jour les valeurs HeaderText pour les ChampsModèle.

Après avoir créé une série d'interfaces d'insertion dans les FooterTemplates, supprimé les SupplierID champs, ainsi que les CategoryID TemplateFields, et amélioré l'esthétique de la grille grâce à la mise en forme et à l'alignement des TemplateFields, le balisage déclaratif de GridView devrait ressembler à ce qui suit :

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    AllowPaging="True" EnableViewState="False" ShowFooter="True">
    <Columns>
        <asp:TemplateField HeaderText="ProductID" InsertVisible="False" 
            SortExpression="ProductID">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" 
                    Text='<%# Bind("ProductID") %>'></asp:Label>
            </ItemTemplate>
            <ItemStyle HorizontalAlign="Center" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" 
                    Text='<%# Bind("ProductName") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewProductName" runat="server"></asp:TextBox>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                    runat="server" ControlToValidate="NewProductName"
                    Display="Dynamic"  ForeColor="
                    ErrorMessage="You must enter a name for the new product.">
                    * </asp:RequiredFieldValidator>
            </FooterTemplate>
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Category" SortExpression="CategoryName">
            <ItemTemplate>
                <asp:Label ID="Label10" runat="server" 
                    Text='<%# Bind("CategoryName") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:DropDownList ID="NewCategoryID" runat="server" 
                    DataSourceID="CategoriesDataSource"
                    DataTextField="CategoryName" DataValueField="CategoryID">
                </asp:DropDownList>
                <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
                    OldValuesParameterFormatString="original_{0}" 
                    SelectMethod="GetCategories" TypeName="CategoriesBLL">
                </asp:ObjectDataSource>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Supplier" SortExpression="SupplierName">
            <ItemTemplate>
                <asp:Label ID="Label11" runat="server" 
                    Text='<%# Bind("SupplierName") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:DropDownList ID="NewSupplierID" runat="server" 
                    DataSourceID="SuppliersDataSource"
                    DataTextField="CompanyName" DataValueField="SupplierID">
                </asp:DropDownList><asp:ObjectDataSource ID="SuppliersDataSource" 
                    runat="server" OldValuesParameterFormatString="original_{0}" 
                    SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
                </asp:ObjectDataSource>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Qty/Unit" SortExpression="QuantityPerUnit">
            <ItemTemplate>
                <asp:Label ID="Label5" runat="server" 
                    Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewQuantityPerUnit" runat="server"></asp:TextBox>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
            <ItemTemplate>
                <asp:Label ID="Label6" runat="server" 
                    Text='<%# Bind("UnitPrice", "{0:c}") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                $<asp:TextBox ID="NewUnitPrice" runat="server" Columns="8" />
                <asp:CompareValidator ID="CompareValidator1" runat="server" 
                    ControlToValidate="NewUnitPrice"
                    ErrorMessage="You must enter a valid currency value greater than 
                        or equal to 0.00. Do not include the currency symbol."
                    ForeColor="" Operator="GreaterThanEqual" Type="Currency" 
                    ValueToCompare="0" Display="Dynamic">
                    * </asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Units In Stock" 
            SortExpression="Units In Stock">
            <ItemTemplate>
                <asp:Label ID="Label7" runat="server" 
                    Text='<%# Bind("UnitsInStock") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewUnitsInStock" runat="server" Columns="5" />
                <asp:CompareValidator ID="CompareValidator2" runat="server" 
                    ControlToValidate="NewUnitsInStock" Display="Dynamic" 
                    ErrorMessage="You must enter a valid numeric value for units 
                        in stock that's greater than or equal to zero."
                    ForeColor="" Operator="GreaterThanEqual" Type="Integer" 
                        ValueToCompare="0">*</asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Units On Order" SortExpression="UnitsOnOrder">
            <ItemTemplate>
                <asp:Label ID="Label8" runat="server" 
                    Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewUnitsOnOrder" runat="server" Columns="5" />
                <asp:CompareValidator ID="CompareValidator3" runat="server" 
                    ControlToValidate="NewUnitsOnOrder" Display="Dynamic" 
                    ErrorMessage="You must enter a valid numeric value for units on 
                        order that's greater than or equal to zero."
                    ForeColor="" Operator="GreaterThanEqual" Type="Integer" 
                    ValueToCompare="0">*</asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Reorder Level" SortExpression="ReorderLevel">
            <ItemTemplate>
                <asp:Label ID="Label9" runat="server" 
                    Text='<%# Bind("ReorderLevel") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewReorderLevel" runat="server" Columns="5" />
                <asp:CompareValidator ID="CompareValidator4" runat="server" 
                    ControlToValidate="NewReorderLevel" Display="Dynamic" 
                    ErrorMessage="You must enter a valid numeric value for reorder 
                        level that's greater than or equal to zero."
                    ForeColor="" Operator="GreaterThanEqual" Type="Integer" 
                    ValueToCompare="0">*</asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
            <ItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server" 
                    Checked='<%# Bind("Discontinued") %>' Enabled="false" />
            </ItemTemplate>
            <FooterTemplate>
                <asp:CheckBox ID="NewDiscontinued" runat="server" />
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Center" />
            <FooterStyle HorizontalAlign="Center" />
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Lorsqu’elle est consultée par le biais d’un navigateur, la ligne du pied de page gridView inclut désormais l’interface d’insertion terminée (voir la figure 10). À ce stade, l’interface d’insertion n’inclut pas de moyen pour l’utilisateur d’indiquer qu’elle a entré les données du nouveau produit et souhaite insérer un nouvel enregistrement dans la base de données. En outre, nous n’avons pas encore abordé la façon dont les données entrées dans le pied de page se traduisent en un nouvel enregistrement dans la Products base de données. À l’étape 4, nous allons examiner comment inclure un bouton Ajouter à l’interface d’insertion et comment exécuter du code lors d’un clic sur postback. L’étape 5 montre comment insérer un nouvel enregistrement à l’aide des données du pied de page.

Le pied de page GridView fournit une interface pour l’ajout d’un nouvel enregistrement

Figure 10 : Le pied de page GridView fournit une interface permettant d’ajouter un nouvel enregistrement (cliquez pour afficher l’image de taille complète)

Étape 4 : Inclure un bouton Ajouter dans l’interface d’insertion

Nous devons inclure un bouton Ajouter quelque part dans l’interface d’insertion, car l’interface d’insertion de la ligne de pied de page ne dispose actuellement pas des moyens pour l’utilisateur d’indiquer qu’il a terminé d’entrer les informations du nouveau produit. Cela peut être placé dans l’un des s existants FooterTemplate ou nous pourrions ajouter une nouvelle colonne à la grille à cet effet. Pour ce tutoriel, placez le bouton Ajouter dans templateField ProductID s FooterTemplate.

Dans le Concepteur, cliquez sur le lien Modifier les modèles dans la balise intelligente de GridView, puis choisissez le champ ProductIDFooterTemplate dans la liste déroulante. Ajoutez un contrôle Web Button (ou un LinkButton ou ImageButton, si vous préférez) au modèle, en définissant son ID à AddProduct, son CommandName sur Insérer et sa propriété Text à Ajouter, comme le montre la figure 11.

Placez le bouton Ajouter dans le FooterTemplate du TemplateField ProductID

Figure 11 : Placer le bouton Ajouter dans templateField ProductID s FooterTemplate (cliquez pour afficher l’image de taille complète)

Une fois que vous avez inclus le bouton Ajouter, testez la page dans un navigateur. Notez que lorsque vous cliquez sur le bouton Ajouter avec des données non valides dans l’interface d’insertion, le postback est court-circuité et le contrôle ValidationSummary indique les données non valides (voir la figure 12). Avec les données appropriées saisies, cliquer sur le bouton Ajouter provoque un envoi des données au serveur. Aucun enregistrement n’est ajouté à la base de données. Nous devons écrire un peu de code pour effectuer l’insertion.

Le postback du bouton Ajouter est court-circuité s’il y a des données non valides dans l’interface d’insertion

Figure 12 : Le postback du bouton Ajouter un bouton est court-circuité s’il existe des données non valides dans l’interface d’insertion (cliquez pour afficher l’image de taille complète)

Remarque

Les contrôles de validation dans l’interface d’insertion n’ont pas été affectés à un groupe de validation. Cela fonctionne correctement tant que l’interface d’insertion est le seul ensemble de contrôles de validation sur la page. Si toutefois, il existe d’autres contrôles de validation sur la page (tels que les contrôles de validation dans l’interface d’édition de la grille), les contrôles de validation dans l’interface d’insertion et les propriétés Ajouter des ValidationGroup boutons doivent être affectés à la même valeur afin d’associer ces contrôles à un groupe de validation particulier. Consultez Dissecting the Validation Controls in ASP.NET 2.0 pour plus d'informations sur le partitionnement des contrôles de validation et des boutons d'une page en groupes de validation.

Étape 5 : Insertion d’un nouvel enregistrement dans laProductstable

Lorsque vous utilisez les fonctionnalités d’édition intégrées de GridView, GridView gère automatiquement tout le travail nécessaire pour effectuer la mise à jour. En particulier, lorsque le bouton Mettre à jour est cliqué, il copie les valeurs entrées à partir de l’interface d’édition vers les paramètres de la collection ObjectDataSource et UpdateParameters lance la mise à jour en appelant la méthode ObjectDataSource.Update() Étant donné que GridView ne fournit pas de fonctionnalités intégrées pour l’insertion, nous devons implémenter du code qui appelle la méthode ObjectDataSource et Insert() copie les valeurs de l’interface d’insertion dans la collection ObjectDataSource InsertParameters .

Cette logique d’insertion doit être exécutée une fois que le bouton Ajouter a été cliqué. Comme discuté dans le didacticiel Ajout et réponse aux boutons dans un GridView, chaque fois qu’un Bouton, LinkButton ou ImageButton dans un GridView est cliqué, l’événement GridView RowCommand se déclenche lors d'un retour de soumission. Cet événement se déclenche si le bouton, LinkButton ou ImageButton a été ajouté explicitement, tel que le bouton Ajouter dans la ligne de pied de page ou s’il a été automatiquement ajouté par GridView (par exemple, linkButtons en haut de chaque colonne lorsque l’option Activer le tri est sélectionnée, ou les LinkButtons dans l’interface de pagination lors de l’activation de la pagination est sélectionnée).

Par conséquent, pour répondre à l’utilisateur en cliquant sur le bouton Ajouter, nous devons créer un gestionnaire d’événements pour l’événement GridView RowCommand . Dans la mesure où cet événement se déclenche chaque fois que n’importe quel bouton, LinkButton ou ImageButton dans GridView est cliqué, il est essentiel que nous continuions uniquement avec la logique d’insertion si la CommandName propriété passée dans le gestionnaire d’événements mappe à la CommandName valeur du bouton Ajouter (Insérer). En outre, nous ne devrions également continuer que si les contrôles de validation signalent des données valides. Pour ce faire, créez un gestionnaire d’événements pour l’événement RowCommand avec le code suivant :

protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
    // Insert data if the CommandName == "Insert" 
    // and the validation controls indicate valid data...
    if (e.CommandName == "Insert" && Page.IsValid)
    {
        // TODO: Insert new record...
    }
}

Remarque

Vous vous demandez peut-être pourquoi le gestionnaire d’événements s'embête à vérifier la propriété Page.IsValid. Après tout, le "postback" ne sera-t-il pas supprimé si des données non valides sont fournies dans l'interface d'insertion ? Cette hypothèse est correcte tant que l’utilisateur n’a pas désactivé JavaScript ou a pris des mesures pour contourner la logique de validation côté client. En bref, il ne faut jamais compter strictement sur la validation côté client ; Une vérification côté serveur pour la validité doit toujours être effectuée avant d’utiliser les données.

À l'étape 1, nous avons créé ProductsDataSource ObjectDataSource afin que sa méthode Insert() soit mappée à la méthode ProductsBLL de la classe AddProduct. Pour insérer le nouvel enregistrement dans la Products table, nous pouvons simplement appeler la méthode ObjectDataSource Insert() :

protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
    // Insert data if the CommandName == "Insert" 
    // and the validation controls indicate valid data...
    if (e.CommandName == "Insert" && Page.IsValid)
    {
        // Insert new record
        ProductsDataSource.Insert();
    }
}

Maintenant que la méthode Insert() a été appelée, il reste à copier les valeurs de l’interface d’insertion vers les paramètres passés à la méthode ProductsBLL de la classe AddProduct. Comme nous l’avons vu dans le didacticiel Examen des événements associés à l’insertion, à la mise à jour et à la suppression, cela peut être effectué via l’événement ObjectDataSource Inserting . Dans l’événement Inserting , nous devons référencer par programmation les contrôles de la Products ligne du pied de page gridView et affecter leurs valeurs à la e.InputParameters collection. Si l’utilisateur omet une valeur comme laisser le TextBox ReorderLevel vide, nous devons spécifier que la valeur insérée dans la base de données doit être NULL. Étant donné que la AddProducts méthode accepte des types nullables pour les champs de base de données nullables, utilisez simplement un type Nullable et définissez sa valeur null dans le cas où l’entrée utilisateur est omise.

protected void ProductsDataSource_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{
    // Programmatically reference Web controls in the inserting interface...
    TextBox NewProductName = 
        (TextBox)Products.FooterRow.FindControl("NewProductName");
    DropDownList NewCategoryID = 
        (DropDownList)Products.FooterRow.FindControl("NewCategoryID");
    DropDownList NewSupplierID = 
        (DropDownList)Products.FooterRow.FindControl("NewSupplierID");
    TextBox NewQuantityPerUnit = 
        (TextBox)Products.FooterRow.FindControl("NewQuantityPerUnit");
    TextBox NewUnitPrice = 
        (TextBox)Products.FooterRow.FindControl("NewUnitPrice");
    TextBox NewUnitsInStock = 
        (TextBox)Products.FooterRow.FindControl("NewUnitsInStock");
    TextBox NewUnitsOnOrder = 
        (TextBox)Products.FooterRow.FindControl("NewUnitsOnOrder");
    TextBox NewReorderLevel = 
        (TextBox)Products.FooterRow.FindControl("NewReorderLevel");
    CheckBox NewDiscontinued = 
        (CheckBox)Products.FooterRow.FindControl("NewDiscontinued");
    // Set the ObjectDataSource's InsertParameters values...
    e.InputParameters["productName"] = NewProductName.Text;
    
    e.InputParameters["supplierID"] = 
        Convert.ToInt32(NewSupplierID.SelectedValue);
    e.InputParameters["categoryID"] = 
        Convert.ToInt32(NewCategoryID.SelectedValue);
    
    string quantityPerUnit = null;
    if (!string.IsNullOrEmpty(NewQuantityPerUnit.Text))
        quantityPerUnit = NewQuantityPerUnit.Text;
    e.InputParameters["quantityPerUnit"] = quantityPerUnit;
    decimal? unitPrice = null;
    if (!string.IsNullOrEmpty(NewUnitPrice.Text))
        unitPrice = Convert.ToDecimal(NewUnitPrice.Text);
    e.InputParameters["unitPrice"] = unitPrice;
    short? unitsInStock = null;
    if (!string.IsNullOrEmpty(NewUnitsInStock.Text))
        unitsInStock = Convert.ToInt16(NewUnitsInStock.Text);
    e.InputParameters["unitsInStock"] = unitsInStock;
    short? unitsOnOrder = null;
    if (!string.IsNullOrEmpty(NewUnitsOnOrder.Text))
        unitsOnOrder = Convert.ToInt16(NewUnitsOnOrder.Text);
    e.InputParameters["unitsOnOrder"] = unitsOnOrder;
    short? reorderLevel = null;
    if (!string.IsNullOrEmpty(NewReorderLevel.Text))
        reorderLevel = Convert.ToInt16(NewReorderLevel.Text);
    e.InputParameters["reorderLevel"] = reorderLevel;
    
    e.InputParameters["discontinued"] = NewDiscontinued.Checked;
}

Une fois le Inserting gestionnaire d’événements terminé, de nouveaux enregistrements peuvent être ajoutés à la Products table de base de données via la ligne de pied de page de GridView. Continuez et essayez d’ajouter plusieurs nouveaux produits.

Amélioration et personnalisation de l’opération Ajouter

Actuellement, le fait de cliquer sur le bouton Ajouter ajoute un nouvel enregistrement à la table de base de données, mais ne fournit aucune sorte de commentaires visuels que l’enregistrement a correctement été ajouté. Dans l’idéal, un contrôle Web Label ou une zone d’alerte côté client informerait l’utilisateur que son insertion s’est terminée avec succès. Je laisse ça comme un exercice pour le lecteur.

GridView utilisé dans ce didacticiel n’applique aucun ordre de tri aux produits répertoriés, ni n’autorise l’utilisateur final à trier les données. Par conséquent, les enregistrements sont classés comme ils se trouvent dans la base de données par leur champ de clé primaire. Étant donné que chaque nouvel enregistrement a une ProductID valeur supérieure à la dernière, chaque fois qu’un nouveau produit est ajouté, il est ajouté à la fin de la grille. Par conséquent, vous pouvez envoyer automatiquement l’utilisateur à la dernière page du GridView après avoir ajouté un nouvel enregistrement. Pour ce faire, ajoutez la ligne de code suivante après l’appel au ProductsDataSource.Insert()RowCommand gestionnaire d’événements pour indiquer que l’utilisateur doit être envoyé à la dernière page après la liaison des données à GridView :

// Indicate that the user needs to be sent to the last page
SendUserToLastPage = true;

SendUserToLastPage est une variable booléenne au niveau de la page qui est initialement affectée à une valeur de false. Dans le gestionnaire d’événements DataBound de GridView, si SendUserToLastPage est faux, la propriété PageIndex est mise à jour pour envoyer l’utilisateur à la dernière page.

protected void Products_DataBound(object sender, EventArgs e)
{
    // Send user to last page of data, if needed
    if (SendUserToLastPage)
        Products.PageIndex = Products.PageCount - 1;
}

La raison pour laquelle la PageIndex propriété est définie dans le DataBound gestionnaire d’événements (par opposition au RowCommand gestionnaire d’événements) est due au fait que lorsque le RowCommand gestionnaire d’événements se déclenche, nous n’avons pas encore ajouté le nouvel enregistrement à la Products table de base de données. Par conséquent, dans le gestionnaire d’événements RowCommand , le dernier index de page (PageCount - 1) représente le dernier index de page avant l’ajout du nouveau produit. Pour la majorité des produits ajoutés, le dernier index de page est le même après l’ajout du nouveau produit. Toutefois, lorsque le produit ajouté génère un nouvel index de page, si nous mettons à jour incorrectement le PageIndex dans le gestionnaire d'événements RowCommand, nous irons à l'avant-dernière page (l'index de la dernière page avant l'ajout du nouveau produit) au lieu du nouvel index de page. Étant donné que le DataBound gestionnaire d’événements se déclenche une fois que le nouveau produit a été ajouté et que les données rebondissent dans la grille, en définissant la PageIndex propriété, nous savons que nous obtenons l’index de dernière page correct.

Enfin, gridView utilisé dans ce tutoriel est assez large en raison du nombre de champs qui doivent être collectés pour l’ajout d’un nouveau produit. En raison de cette largeur, une disposition verticale de DetailsView peut être préférée. La largeur globale de GridView peut être réduite en collectant moins d’entrées. Nous n'avons peut-être pas besoin de collecter les champs UnitsOnOrder, UnitsInStock et ReorderLevel lors de l'ajout d'un nouveau produit ; dans ce cas, ces champs pourraient être supprimés de la GridView.

Pour ajuster les données collectées, nous pouvons utiliser l’une des deux approches suivantes :

  • Continuez à utiliser la AddProduct méthode qui attend des valeurs pour les champs UnitsOnOrder, UnitsInStock et ReorderLevel. Dans le Inserting gestionnaire d’événements, fournissez des valeurs par défaut codées en dur à utiliser pour ces entrées qui ont été supprimées de l’interface d’insertion.
  • Créez une nouvelle surcharge de la méthode AddProduct dans la classe ProductsBLL qui n’accepte pas les entrées pour les champs UnitsOnOrder, UnitsInStock et ReorderLevel. Ensuite, dans la page ASP.NET, configurez ObjectDataSource pour utiliser cette nouvelle surcharge.

L’une ou l’autre option fonctionne également. Dans les didacticiels précédents, nous avons utilisé cette dernière option, créant plusieurs surcharges pour la méthode ProductsBLL de la classe UpdateProduct.

Résumé

GridView ne dispose pas des fonctionnalités d’insertion intégrées trouvées dans DetailsView et FormView, mais avec un peu d’effort, une interface d’insertion peut être ajoutée à la ligne de pied de page. Pour afficher la ligne du pied de page dans un GridView, définissez simplement sa propriété ShowFooter sur true. Le contenu de la ligne du pied de page peut être personnalisé pour chaque champ en convertissant le champ en un TemplateField et en ajoutant l'interface d'insertion à l’objet FooterTemplate. Comme nous l’avons vu dans ce tutoriel, le FooterTemplate fichier peut contenir des boutons, des zones de texte, des listes déroulantes, des checkBoxes, des contrôles de source de données pour remplir des contrôles Web pilotés par les données (tels que DropDownLists) et des contrôles de validation. Outre les contrôles permettant de collecter l’entrée de l’utilisateur, un bouton Ajouter, LinkButton ou ImageButton est nécessaire.

Lorsque le bouton Ajouter est cliqué, la méthode ObjectDataSource Insert() est appelée pour démarrer le flux de travail d’insertion. L'ObjectDataSource appellera ensuite la méthode configurée d'insertion (la méthode de la classe ProductsBLL de AddProduct, dans ce tutoriel). Nous devons copier les valeurs de l’interface d’insertion de GridView dans la collection ObjectDataSource InsertParameters avant l’appel de la méthode Insert. Pour ce faire, référencez par programmation les contrôles Web d’interface d’insertion dans le gestionnaire d’événements ObjectDataSource Inserting .

Ce tutoriel complète nos techniques d’amélioration de l’apparence de GridView. L’ensemble suivant de didacticiels explique comment utiliser des données binaires telles que des images, des fichiers PDF, des documents Word, etc. et les contrôles Web de données.

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 en tant que consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 en 24 heures. On peut le joindre à mitchell@4GuysFromRolla.com.

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 Bernadette Leigh. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.