C # DropDownList avec un dictionnaire comme source de données

112

Je veux définir DataTextFieldet DataValueFieldd'une Dropdownlist(languageList) en utilisant un dictionnaire (liste) de languageCod(en-gb) comme clé et un nom de langue (anglais) comme texte à afficher.

Code pertinent:

string[] languageCodsList= service.LanguagesAvailable();
Dictionary<string, string> list = 
                   new Dictionary<string, string>(languageCodsList.Length);

foreach (string cod in languageCodsList)
{
    CultureInfo cul = new CultureInfo(cod);
    list.Add(cod, cul.DisplayName);
}
languageList.DataSource = list;
languageList.DataBind();

Comment puis-je définir DataTextFieldet DataValueField?

VansFannel
la source

Réponses:

205

Ainsi, vous pouvez définir DataTextField et DataValueField de DropDownList en utilisant les textes "Key" et "Value":

    Dictionary<string, string> list = new Dictionary<string, string>();
    list.Add("item 1", "Item 1");
    list.Add("item 2", "Item 2");
    list.Add("item 3", "Item 3");
    list.Add("item 4", "Item 4");

    ddl.DataSource = list;
    ddl.DataTextField = "Value";
    ddl.DataValueField = "Key";
    ddl.DataBind();
Canavar
la source
12
Je recommanderais de définir TextField sur "key" et ValueField sur Value. Je pense que c'est plus intuitif.
MGOwen
15
@MGOwen Il peut sembler intuitif de définir DataValueField sur Value, à cause de la "Value" commune, mais il est en fait illogique dans l'utilisation régulière de la structure de données / contrôle. Pour plus de détails à ce sujet, consultez mon commentaire sur la réponse de Jon Skeet.
Dani
Je ne vois pas de liste. Ajouter qui prend 2 arguments .. un seul qui prend un argument. est-ce winforms ??
2012 à
@hrh alors vous n'utilisez probablement pas a Dictionary<TKey, TValue>, mais peut-être un List<T>.
sshow
@Canavar est-il possible de définir le champ DataText comme "clé-valeur" ....? Comment puis-je le faire.
Sravan Kumar
11

Lorsqu'un dictionnaire est énuméré, il produira des KeyValuePair<TKey,TValue>objets ... il vous suffit donc de spécifier "Valeur" et "Clé" pour DataTextFieldet DataValueFieldrespectivement, pour sélectionner les propriétés Valeur / Clé .

Grâce au commentaire de Joe, j'ai relu la question pour trouver le bon chemin. Normalement, je m'attendrais à ce que la "clé" dans le dictionnaire soit le texte affiché et la "valeur" soit la valeur extraite. Cependant, votre exemple de code les utilise dans l'autre sens. À moins que vous n'en ayez vraiment besoin, vous voudrez peut-être envisager d'écrire votre code comme suit:

list.Add(cul.DisplayName, cod);

(Et puis en changeant la liaison pour utiliser "Key" pour DataTextFieldet "Value" pour DataValueField, bien sûr.)

En fait, je suggérerais que, comme il semble que vous voulez vraiment une liste plutôt qu'un dictionnaire, vous voudrez peut-être reconsidérer l'utilisation d'un dictionnaire en premier lieu. Vous pouvez simplement utiliser un List<KeyValuePair<string, string>>:

string[] languageCodsList = service.LanguagesAvailable();
var list = new List<KeyValuePair<string, string>>();

foreach (string cod in languageCodsList)
{
    CultureInfo cul = new CultureInfo(cod);
    list.Add(new KeyValuePair<string, string>(cul.DisplayName, cod));
}

Vous pouvez également utiliser une liste de CultureInfovaleurs simples . LINQ rend cela très simple:

var cultures = service.LanguagesAvailable()
                      .Select(language => new CultureInfo(language));
languageList.DataTextField = "DisplayName";
languageList.DataValueField = "Name";
languageList.DataSource = cultures;
languageList.DataBind();

Si vous n'utilisez pas LINQ, vous pouvez toujours utiliser une boucle foreach normale:

List<CultureInfo> cultures = new List<CultureInfo>();
foreach (string cod in service.LanguagesAvailable())
{
    cultures.Add(new CultureInfo(cod));
}
languageList.DataTextField = "DisplayName";
languageList.DataValueField = "Name";
languageList.DataSource = cultures;
languageList.DataBind();
Jon Skeet
la source
3
En fait, c'est incorrect - voir mon commentaire sur la réponse acceptée.
Winston Smith
Ah, j'ai mal lu la question. Il me semble déroutant de les mettre dans un dictionnaire dans le «mauvais» sens. Éditera ma réponse.
Jon Skeet
1
@JonSkeet La raison de l'association "vers l'arrière" est que les données stockées dans le dictionnaire en tant que paire clé / valeur utilisent normalement la clé (valeur de recherche) comme association de données (par exemple pour le référencement de la base de données), et dans une liste déroulante , cela correspond au DataValueField, c'est-à-dire à la valeur de retour d'un POST, qui vous en dit plus sur l'élément sélectionné que le DataTextField, c'est-à-dire la valeur d'affichage. (Les listes DropDown ont juste une mauvaise convention de dénomination)
Dani
6

Si DropDownList est déclaré dans votre page aspx et non dans le codebehind, vous pouvez le faire comme ceci.

.aspx:

<asp:DropDownList ID="ddlStatus" runat="server" DataSource="<%# Statuses %>"
     DataValueField="Key" DataTextField="Value"></asp:DropDownList>

.aspx.cs:

protected void Page_Load(object sender, EventArgs e)
{
    ddlStatus.DataBind();
    // or use Page.DataBind() to bind everything
}

public Dictionary<int, string> Statuses
{
    get 
    {
        // do database/webservice lookup here to populate Dictionary
    }
};
Matt Frear
la source
J'ai voté pour. Il est à noter qu'il est OBLIGATOIRE que ce soit un objet côté serveur à évaluer. Vous ne pouvez pas le transmettre en ligne en utilisant <% # syntax%>. Que ce soit un <script runat = "server">, ou comme vu dans l'exemple de Matt ci-dessus, à vous. Cela fonctionne vraiment.
Barry
5

Utilisez simplement "Clé" et "Valeur"

user98296
la source