Suis le coach...pour ajouter une option dans une liste déroulante liée à une source de données
Prenons l'exemple d'une liste déroulante (cf. Figures 1 et 2) qui affiche des rubriques de bonnes affaires à partir d'une source de données contenant une table [Rubriques]. L'objectif est d'ajouter une option par défaut "Sélectionnez une rubrique" pour inviter l'utilisateur à faire un choix parmi les options proposées.
Figure 1 - Vue de la liste déroulante par défaut
Figure 2 - Vue de la liste déroulante complète
Marche à suivre :
Pour construire la liste, il vous faut :
- un contrôle de source de données de type SqlDataSource (ou ObjectDataSource) qui pointe vers la base de données des bonnes affaires. La chaîne de connexion (nommée csAffairesSansRisque dans l'exemple) est lue à partir du fichier de configuration web.config.
- un contrôle d'affichage de type DropDownList lié au contrôle précédent via l'attribut DataSourceID.
- L'attribut DataTextField donne le champ de la table dans la source de données qui est assigné au texte de chaque option.
- L'attribut DataValueField donne le champ de la table dans la source de données qui est assigné à la valeur de chaque option.
<asp:SqlDataSource ID="SqlLstRubriques" runat="server"
ConnectionString="<% ConnectionStrings:csAffairesSansRisque%>"
SelectCommand="SELECT * FROM [Rubriques]">
</asp:SqlDataSource>
Rubrique :
<asp:DropDownList ID="ddlRubriques" runat="server" AutoPostBack="True"
DataSourceID="SqlLstRubriques"
DataTextField="Rub_Nom" DataValueField="Rub_Id">
</asp:DropDownList>
Pour ajouter l'option d'aide en tête de liste, vous pouvez soit le faire par programmation, soit en déclaratif tout simplement comme ceci :
<asp:SqlDataSource ...></asp:SqlDataSource>
Rubrique :
<asp:DropDownList ID="ddlRubriques" runat="server" AutoPostBack="True"
DataSourceID="SqlLstRubriques"
DataTextField="Rub_Nom" DataValueField="Rub_Id">
<asp:ListItem Value="">Sélectionnez une rubrique</asp:ListItem>
</asp:DropDownList>
Malheureusement, l'option est écrasée au moment de la liaison de données. Pour prévenir ASP.NET qu'il doit préserver les options que vous avez pu insérer par vous-même, il suffit d'ajouter l'attribut AppendDataBoundItems au contrôle DropDownList à la valeur true.
<asp:SqlDataSource ...></asp:SqlDataSource>
Rubrique :
<asp:DropDownList ID="ddlRubriques" runat="server" AutoPostBack="True"
DataSourceID="SqlLstRubriques" AppendDataBoundItems="true"
DataTextField="Rub_Nom" DataValueField="Rub_Id">
<asp:ListItem Value="">Sélectionnez une rubrique</asp:ListItem>
</asp:DropDownList>
Allons un peu plus loin...
Supposons maintenant que cette liste déroulante est elle-même dans un formulaire (cf. Figure 3) de saisie d’une petite annonce, construit à l’aide du contrôle serveur FormView d’ASP.NET 2.0.
Figure 3 - Vue du contrôle FormView en mode d’insertion
Dans ce cas, il y a deux contextes de liaison de données :
- un premier, sur le formulaire qui est lié à une source de données pointant sur une table [Annonces] contenant le texte de l'annonce, la rubrique etc...
- un second, sur la liste déroulante qui est liée à la source de données pointant sur la table [Rubriques] vue précédemment. Mais attention ! La liste déroulante est aussi liée au premier contexte de liaison. En effet, la valeur sélectionnée donne l'Id de la rubrique à mémoriser avec l'annonce.
Dans la base de données, la table [Annonces] ne contient pas directement évidemment de champ <nom> pour la rubrique. Elle contient en réalité un ID (clé étrangère) rapatrié de la table [Rubriques]. Mais on ne peut pas raisonnablement demander à l'utilisateur de connaître l'id de la rubrique dans laquelle il souhaite publier son annonce. L'idéal est donc de remplacer l’ID par le nom de la rubrique associée, c'est-à-dire à remplacer la zone de texte (qui est la représentation par défaut du champ dans le formulaire en mode d'insertion) par une liste déroulante pour proposer une aide à la saisie à l’utilisateur.
Du coup, on retrouve la même définition de la liste déroulante que précédemment excepté que cette fois elle est encapsulée dans le modèle InsertItemTemplate du FormView. Et surtout, elle est liée à la source de données du FormView via l'attribut SelectedValue='<%# Bind("Rub_Id")%> qui charge le champ Rub_Id de l'enregistrement Annonce avec la valeur sélectionnée dans la liste.
<asp:SqlDataSource ID="SqlAnnonces" runat="server"
ConnectionString="<%$ ConnectionStrings:csAffairesSansRisque %>"
InsertCommand="INSERT INTO [Annonces] ([Ann_Texte], [Rub_Id])
VALUES (@Ann_Texte, @Rub_Id)"
SelectCommand="SELECT * FROM [Annonces]" >
<InsertParameters>
<asp:Parameter Name="Ann_Texte" Type="String" />
<asp:Parameter Name="Rub_Id" Type="Int32" />
</InsertParameters>
</asp:SqlDataSource>
<asp:FormView ID="FormView1" runat="server" DataKeyNames="Ann_Id"
DataSourceID="SqlAnnonces" DefaultMode="Insert">
<InsertItemTemplate>
Texte de l'annonce:
<asp:TextBox ID="txtTexteAnnonce" runat="server"
Text='<%# Bind("Ann_Texte") %>'
TextMode="MultiLine" Height="50px"></asp:TextBox>
<br /><br />
<asp:SqlDataSource ID="SqlLstRubriques" runat="server"
ConnectionString="<%$ ConnectionStrings:csAffairesSansRisque %>"
SelectCommand="SELECT * FROM [Rubriques]"></asp:SqlDataSource>
Rubrique :
<asp:DropDownList ID="ddlRubriques" runat="server" AutoPostBack="True"
DataSourceID="SqlLstRubriques" DataTextField="Rub_Nom"
DataValueField="Rub_Id" SelectedValue='<%# Bind("Rub_Id") %>'
AppendDataBoundItems="true">
<asp:ListItem Value="">Sélectionnez une rubrique</asp:ListItem>
</asp:DropDownList>
<br /><br />
<asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True"
CommandName="Insert" Text="Insérer"></asp:LinkButton>
<asp:LinkButton ID="InsertCancelButton" runat="server"
CausesValidation="False" CommandName="Cancel"
Text="Annuler"></asp:LinkButton>
</InsertItemTemplate>
</asp:FormView>
Se pose alors un dernier souci, lié au fait qu'on a donc configuré une liaison de données sur la liste déroulante. Que se passe-t-il lorsque l'option sélectionnée est celle que l'on a rajouté en tête de liste ? Et oui, la valeur de cette option ne correspond à aucun Id de rubrique valide dans la base de données.
La solution est :
- de configurer la valeur de l'option rajoutée à une valeur vide :
<asp:ListItem Value="">Sélectionnez une rubrique</asp:ListItem>
- d'ajouter un contrôle de validation ASP.NET 2.0 de type RequiredFieldValidator pour empêcher l'insertion si une valeur vide est sélectionnée dans la liste déroulante.
<asp:DropDownList ID="ddlRubriques" runat="server" AutoPostBack="True"
DataSourceID="SqlLstRubriques" DataTextField="Rub_Nom"
DataValueField="Rub_Id" SelectedValue='<%# Bind("Rub_Id") %>'
AppendDataBoundItems="true">
<asp:ListItem Value="">Sélectionnez une rubrique</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="valControleListeVide" runat="server"
ErrorMessage="Vous devez sélectionnez une rubrique"
Text="*" ControlToValidate="ddlRubriques" Display="Dynamic">
</asp:RequiredFieldValidator>
Notez que si vous utilisez l'attribut ErrorMessage pour afficher le message en cas d'erreur au lieu de l'attribut Text, il vous faut ajouter un contrôle de type ValidationSummary, par exemple en haut de la page, pour afficher les messages d'erreur de validation de données :
<asp:ValidationSummary ID="valResume" runat="server"
ShowMessageBox="true" ShowSummary="false" />
Et le tour est joué !
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :