2010-06-17 3 views
151

Dans C# WinApp, comment puis-je ajouter du texte et de la valeur aux éléments de ma zone de liste déroulante? je fait une recherche et généralement les réponses utilisent « La liaison à une source » .. mais dans mon cas, je n'ai pas une source prête dans mon programme ... contraignant Comment puis-je faire quelque chose comme ceci:ComboBox: Ajout de texte et de valeur à un élément (pas de source de liaison)

combo1.Item[1] = "DisplayText"; 
combo1.Item[1].Value = "useful Value" 
+0

Je sais que c'est vieux, mais pour les nouveaux lecteurs, la meilleure réponse est de @MertCingoz ci-dessous. Pas de classe spéciale à gérer et pas besoin de surcharger la méthode ToString(). – dshrout

Répondre

286

Vous devez créer votre propre type de classe et remplacer le ToString () pour retourner le texte que vous voulez. Voici un exemple simple d'une classe, vous pouvez utiliser:

public class ComboboxItem 
{ 
    public string Text { get; set; } 
    public object Value { get; set; } 

    public override string ToString() 
    { 
     return Text; 
    } 
} 

Ce qui suit est un simple exemple de son utilisation:

private void Test() 
{ 
    ComboboxItem item = new ComboboxItem(); 
    item.Text = "Item text1"; 
    item.Value = 12; 

    comboBox1.Items.Add(item); 

    comboBox1.SelectedIndex = 0; 

    MessageBox.Show((comboBox1.SelectedItem as ComboboxItem).Value.ToString()); 
} 
+3

Avons-nous vraiment besoin de cette nouvelle classe ComboboxItem? Je pense qu'il existe déjà un appelé ListItem –

+11

Je crois que cela peut seulement être disponible dans ASP.NET et pas WinForms. –

+0

oui :(malheureusement, il est seulement dans ASP.net ... alors que puis-je faire maintenant? – Bohn

12

Ceci est l'un des moyens qui vient à l'esprit:

combo1.Items.Add(new ListItem("Text", "Value"))

et pour changer le texte ou la valeur d'un élément, vous pouvez le faire comme ceci:

combo1.Items[0].Text = 'new Text'; 

combo1.Items[0].Value = 'new Value'; 

Il n'existe aucune classe appelée ListItem dans Windows Forms. Il n'existe que dans ASP.NET, donc vous devrez écrire votre propre classe avant de l'utiliser, comme @Adam Markowitz l'a fait dans his answer.

Vérifiez également ces pages, ils peuvent aider:

+2

Sauf si je me trompe, ListItem est seulement disponible dans ASP.NET –

+0

oui :(malheureusement, il est seulement dans ASP.net ... alors que puis-je faire maintenant? – Bohn

+0

Oui, il suffit de le remarquer et j'ai mis à jour ma réponse –

11

Je ne sais pas si cela fonctionnera pour la situation donnée dans la message original (sans parler du fait que ce soit deux ans plus tard), mais cet exemple fonctionne pour moi:

Hashtable htImageTypes = new Hashtable(); 
htImageTypes.Add("JPEG", "*.jpg"); 
htImageTypes.Add("GIF", "*.gif"); 
htImageTypes.Add("BMP", "*.bmp"); 

foreach (DictionaryEntry ImageType in htImageTypes) 
{ 
    cmbImageType.Items.Add(ImageType); 
} 
cmbImageType.DisplayMember = "key"; 
cmbImageType.ValueMember = "value"; 

pour lire votre valeur de retour, vous devrez jeter la propriété SelectedItem à un objec DictionaryEntry t, et vous pouvez ensuite évaluer les propriétés Key et Value de cela. Par exemple:

DictionaryEntry deImgType = (DictionaryEntry)cmbImageType.SelectedItem; 
MessageBox.Show(deImgType.Key + ": " + deImgType.Value); 
161
// Bind combobox to dictionary 
Dictionary<string, string>test = new Dictionary<string, string>(); 
     test.Add("1", "dfdfdf"); 
     test.Add("2", "dfdfdf"); 
     test.Add("3", "dfdfdf"); 
     comboBox1.DataSource = new BindingSource(test, null); 
     comboBox1.DisplayMember = "Value"; 
     comboBox1.ValueMember = "Key"; 

// Get combobox selection (in handler) 
string value = ((KeyValuePair<string, string>)comboBox1.SelectedItem).Value; 
+2

Fonctionne parfaitement et cela devrait être la réponse choisie. Mais ne pouvons-nous pas utiliser comboBox1.SelectedText au lieu de lancer .SelectedItem et prendre .Value? –

+0

@fab Comment trouver un objet dans la zone de liste déroulante avec une certaine touche – Smith

+0

Est-il possible de sélectionner un élément dans la zone de liste déroulante en fonction de la clé du dictionnaire? comme sélectionner la touche 3 pour que l'élément avec la touche 3 soit sélectionné. – Dror

92

Vous pouvez utiliser la classe anonyme comme ceci:

comboBox.DisplayMember = "Text"; 
comboBox.ValueMember = "Value"; 

comboBox.Items.Add(new { Text = "report A", Value = "reportA" }); 
comboBox.Items.Add(new { Text = "report B", Value = "reportB" }); 
comboBox.Items.Add(new { Text = "report C", Value = "reportC" }); 
comboBox.Items.Add(new { Text = "report D", Value = "reportD" }); 
comboBox.Items.Add(new { Text = "report E", Value = "reportE" }); 

MISE À JOUR: Bien que le code ci-dessus affiche correctement dans zone de liste déroulante, vous ne pourrez pas utiliser SelectedValue ou SelectedText propriétés de ComboBox. Pour pouvoir utiliser ceux-ci, zone de liste déroulante bind comme ci-dessous:

comboBox.DisplayMember = "Text"; 
comboBox.ValueMember = "Value"; 

var items = new[] { 
    new { Text = "report A", Value = "reportA" }, 
    new { Text = "report B", Value = "reportB" }, 
    new { Text = "report C", Value = "reportC" }, 
    new { Text = "report D", Value = "reportD" }, 
    new { Text = "report E", Value = "reportE" } 
}; 

comboBox.DataSource = items; 
+10

Je voudrais modifier cela légèrement parce qu'un programmeur est susceptible d'avoir besoin d'une boucle for avec cela. Au lieu d'un tableau j'ai utilisé une liste 'List items = new Liste ();' Puis j'ai été capable d'utiliser la méthode 'items.Ajouter (new {Text = "report A", Value = "reportA"}); 'dans la boucle. – Andrew

+0

Andrew, avez-vous obtenu la liste pour travailler avec la propriété SelectedValue? –

+2

Comment le lire? – Venkat

1

Suite à la réponse d'Adam Markowitz, voici un moyen objectif général de (relativement) définissant simplement les ItemSource valeurs d'un combobox être enums, tout en montrant l'attribut 'Description' à l'utilisateur.(On pourrait penser que tout le monde voudrait faire cela pour que ce soit un paquebot, mais ce n'est pas le cas, et c'est la façon la plus élégante que j'ai trouvée).

Tout d'abord, créez cette classe simple pour convertir une valeur Enum dans un élément ComboBox:

public class ComboEnumItem { 
    public string Text { get; set; } 
    public object Value { get; set; } 

    public ComboEnumItem(Enum originalEnum) 
    { 
     this.Value = originalEnum; 
     this.Text = this.ToString(); 
    } 

    public string ToString() 
    { 
     FieldInfo field = Value.GetType().GetField(Value.ToString()); 
     DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; 
     return attribute == null ? Value.ToString() : attribute.Description; 
    } 
} 

En second lieu dans votre gestionnaire d'événements OnLoad, vous devez définir la source de votre zone de liste déroulante à une liste de ComboEnumItems basé sur tous les Enum dans votre type Enum. Cela peut être réalisé avec Linq. Ensuite, il suffit régler la DisplayMemberPath:

void OnLoad(object sender, RoutedEventArgs e) 
    { 
     comboBoxUserReadable.ItemsSource = Enum.GetValues(typeof(EMyEnum)) 
         .Cast<EMyEnum>() 
         .Select(v => new ComboEnumItem(v)) 
         .ToList(); 

     comboBoxUserReadable.DisplayMemberPath = "Text"; 
     comboBoxUserReadable.SelectedValuePath= "Value"; 
    } 

Maintenant, l'utilisateur choisira parmi une liste de votre facile à utiliser Descriptions, mais ce qu'ils choisissent sera la valeur enum que vous pouvez utiliser dans le code. Pour accéder à la sélection de l'utilisateur dans le code, comboBoxUserReadable.SelectedItem sera le ComboEnumItem et comboBoxUserReadable.SelectedValue sera le EMyEnum.

5
//set 
comboBox1.DisplayMember = "Value"; 
//to add 
comboBox1.Items.Add(new KeyValuePair("2", "This text is displayed")); 
//to access the 'tag' property 
string tag = ((KeyValuePair< string, string >)comboBox1.SelectedItem).Key; 
MessageBox.Show(tag); 
3

Un exemple en utilisant DataTable:

DataTable dtblDataSource = new DataTable(); 
dtblDataSource.Columns.Add("DisplayMember"); 
dtblDataSource.Columns.Add("ValueMember"); 
dtblDataSource.Columns.Add("AdditionalInfo"); 

dtblDataSource.Rows.Add("Item 1", 1, "something useful 1"); 
dtblDataSource.Rows.Add("Item 2", 2, "something useful 2"); 
dtblDataSource.Rows.Add("Item 3", 3, "something useful 3"); 

combo1.Items.Clear(); 
combo1.DataSource = dtblDataSource; 
combo1.DisplayMember = "DisplayMember"; 
combo1.ValueMember = "ValueMember"; 

    //Get additional info 
    foreach (DataRowView drv in combo1.Items) 
    { 
     string strAdditionalInfo = drv["AdditionalInfo"].ToString(); 
    } 

    //Get additional info for selected item 
    string strAdditionalInfo = (combo1.SelectedItem as DataRowView)["AdditionalInfo"].ToString(); 

    //Get selected value 
    string strSelectedValue = combo1.SelectedValue.ToString(); 
2

J'ai bien aimé la réponse de fabuleux, mais ne voulait pas utiliser un dictionnaire pour ma situation si je substitue une liste de tuples.

// set up your data 
public static List<Tuple<string, string>> List = new List<Tuple<string, string>> 
{ 
    new Tuple<string, string>("Item1", "Item2") 
} 

// bind to the combo box 
comboBox.DataSource = new BindingSource(List, null); 
comboBox.ValueMember = "Item1"; 
comboBox.DisplayMember = "Item2"; 

//Get selected value 
string value = ((Tuple<string, string>)queryList.SelectedItem).Item1; 
8

Vous pouvez utiliser Dictionary objet au lieu de créer une classe personnalisée pour ajouter du texte et de la valeur dans un Combobox.

Ajouter les clés et valeurs dans un Dictionary Objet:

Dictionary<string, string> comboSource = new Dictionary<string, string>(); 
comboSource.Add("1", "Sunday"); 
comboSource.Add("2", "Monday"); 

Bind la source objet Dictionnaire Combobox:

comboBox1.DataSource = new BindingSource(comboSource, null); 
comboBox1.DisplayMember = "Value"; 
comboBox1.ValueMember = "Key"; 

récupérer la clé et de la valeur:

string key = ((KeyValuePair<string,string>)comboBox1.SelectedItem).Key; 
string value = ((KeyValuePair<string,string>)comboBox1.SelectedItem).Value; 

Source complète: Combobox Text nd Value

1

Vous pouvez utiliser un type générique:

public class ComboBoxItem<T> 
{ 
    private string Text { get; set; } 
    public T Value { get; set; } 

    public override string ToString() 
    { 
     return Text; 
    } 

    public ComboBoxItem(string text, T value) 
    { 
     Text = text; 
     Value = value; 
    } 
} 

Exemple d'utilisation d'un simple int-Type:

private void Fill(ComboBox comboBox) 
    { 
     comboBox.Items.Clear(); 
     object[] list = 
      { 
       new ComboBoxItem<int>("Architekt", 1), 
       new ComboBoxItem<int>("Bauträger", 2), 
       new ComboBoxItem<int>("Fachbetrieb/Installateur", 3), 
       new ComboBoxItem<int>("GC-Haus", 5), 
       new ComboBoxItem<int>("Ingenieur-/Planungsbüro", 9), 
       new ComboBoxItem<int>("Wowi", 17), 
       new ComboBoxItem<int>("Endverbraucher", 19) 
      }; 

     comboBox.Items.AddRange(list); 
    } 
0

J'ai eu le même problème, ce que je faisais était d'ajouter une nouvelle ComboBox avec juste la valeur dans le même index puis le premier, et puis quand je change le combo principal l'index dans le deuxième change en même temps, alors je prends la valeur du deuxième combo et l'utilise.

Voici le code:

public Form1() 
{ 
    eventos = cliente.GetEventsTypes(usuario); 

    foreach (EventNo no in eventos) 
    { 
     cboEventos.Items.Add(no.eventno.ToString() + "--" +no.description.ToString()); 
     cboEventos2.Items.Add(no.eventno.ToString()); 
    } 
} 

private void lista_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    lista2.Items.Add(lista.SelectedItem.ToString()); 
} 

private void cboEventos_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    cboEventos2.SelectedIndex = cboEventos.SelectedIndex; 
} 
0

Classe creat:

namespace WindowsFormsApplication1 
{ 
    class select 
    { 
     public string Text { get; set; } 
     public string Value { get; set; } 
    } 
} 

Codes Form1:

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      List<select> sl = new List<select>(); 
      sl.Add(new select() { Text = "", Value = "" }); 
      sl.Add(new select() { Text = "AAA", Value = "aa" }); 
      sl.Add(new select() { Text = "BBB", Value = "bb" }); 
      comboBox1.DataSource = sl; 
      comboBox1.DisplayMember = "Text"; 
     } 

     private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
     { 

      select sl1 = comboBox1.SelectedItem as select; 
      t1.Text = Convert.ToString(sl1.Value); 

     } 

    } 
} 
0

Voici comment Visual Studio 2013 le fait:

Simple article:

comboBox1->Items->AddRange(gcnew cli::array<System::Object^>(1) { L"Combo Item 1" }); 

Articles multiples:

comboBox1->Items->AddRange(gcnew cli::array<System::Object^>(3) 
{ 
    L"Combo Item 1", 
    L"Combo Item 2", 
    L"Combo Item 3" 
}); 

Pas besoin de faire de la classe ou overrides inclure toute autre chose. Et oui, les appels comboBox1->SelectedItem et comboBox1->SelectedIndex fonctionnent toujours.

0

Ceci est similaire à certaines des autres réponses, mais est compact et évite la conversion en dictionnaire si vous avez déjà une liste.

Compte tenu d'un ComboBox « combobox » sur une forme de fenêtres et une classe SomeClass avec la propriété type stringName,

List<SomeClass> list = new List<SomeClass>(); 

combobox.DisplayMember = "Name"; 
combobox.DataSource = list; 

Ce qui signifie que le SelectedItem est un objet SomeClass de list, et chaque élément combobox sera être affiché en utilisant son nom.

+0

True! J'ai utilisé 'DisplayMember' avant ... J'oublie toujours qu'il existe. Je me suis habitué à la solution que j'ai trouvée avant de faire attention à cette propriété, cela n'aidera pas toujours. Toutes les classes n'ont pas de propriété 'Name' ou' Tag', ou ont une propriété de chaîne qui pourrait être utilisée arbitrairement comme texte d'affichage. –

+0

C'est un bon point. Si vous pouvez modifier la classe, cela peut valoir la peine d'ajouter une telle propriété à la classe, par exemple une propriété 'ComboBoxText' (qui pourrait renvoyer la méthode ToString() si disponible). Alternativement, si la classe n'est pas modifiable, il pourrait être possible de créer une classe dérivée dans laquelle la propriété 'ComboBoxText' pourrait être implémentée. Cela ne vaut que si vous devez ajouter la classe à un ComboBox plusieurs fois. Sinon, il est plus simple d'utiliser un dictionnaire comme expliqué dans l'une des autres réponses. –

+0

Hey Alex, j'ai répondu avec l'ethod que j'utilise habituellement dans ces cas. Je pense que c'est assez proche de ce que vous avez dit ou peut-être que je n'ai pas compris ce que vous avez dit. Je n'ai pas dérivé de la classe parce que certaines classes pourraient vous demander d'implémenter des méthodes que nous ne voulons pas remplacer (donc nous aurions un tas de méthodes avec un simple 'base.Method();'), aussi vous Vous devez créer une classe dérivée pour chaque type différent que vous souhaitez ajouter aux zones de liste déroulante ou aux zones de liste. La classe que j'ai faite est flexible, vous pouvez l'utiliser avec n'importe quel type sans effort supplémentaire. Regardez ci-dessous pour ma réponse, et dites-moi ce que vous pensez :) –

0

Ceci est une solution très simple pour les formulaires Windows si tout est nécessaire est la valeur finale en tant que (chaîne). Les noms des éléments seront affichés sur la liste déroulante et la valeur sélectionnée peut être facilement comparée.

List<string> items = new List<string>(); 

// populate list with test strings 
for (int i = 0; i < 100; i++) 
      items.Add(i.ToString()); 

// set data source 
testComboBox.DataSource = items; 

et le gestionnaire d'événements obtenir la valeur (chaîne) de la valeur sélectionnée

string test = testComboBox.SelectedValue.ToString(); 
10

Vous devez utiliser dynamic objet pour résoudre élément ComboBox dans l'exécution.

comboBox.DisplayMember = "Text"; 
comboBox.ValueMember = "Value"; 

comboBox.Items.Add(new { Text = "Text", Value = "Value" }); 

(comboBox.SelectedItem as dynamic).Value 
+0

Ceci est bien mieux que de créer une classe séparée et de surcharger ToString() . – dshrout

3

Vous pouvez utiliser ce code combox add item with text and its value

private void ComboBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e) 
 
     { 
 
      
 
      combox.Items.Insert(0, "Copenhagen"); 
 
      combox.Items.Insert(1, "Tokyo"); 
 
      combox.Items.Insert(2, "Japan"); 
 
      combox.Items.Insert(0, "India"); 
 
      
 
      
 
     }

pour insérer des éléments dans Combox avec le texte et la valeur. et ici sa xaml code for combox

+0

S'il vous plaît expliquer votre solution. –

+0

Tout simplement, ajoutez les pays suivants dans leurs index respectifs dans une combox. Lorsque vous l'exécutez. Une combox apparaît avec une option qui est à 0 index.Si vous cliquez sur la combox l'autre option suivante affichera –

+0

cela ne fonctionne pas pour les ID c'est simplement un moyen d'indexer la liste, ce n'est pas ce que la question était sur –

1

Si quelqu'un est toujours intéressé, voici une classe simple et flexible pour un élément ComboBox avec un texte et une valeur de tout type (très similaire à l'exemple d'Adam Markowitz):

public class ComboBoxItem<T> 
{ 
    public string Name; 
    public T value = default(T); 

    public ComboBoxItem(string Name, T value) 
    { 
     this.Name = Name; 
     this.value = value; 
    } 

    public override string ToString() 
    { 
     return Name; 
    } 
} 

utilisation du <T> est mieux que de déclarer la value comme object, car avec object vous auriez alors à garder une trace du type que vous avez utilisé pour chaque élément, et le jeta dans votre code pour l'utiliser correctement. Je l'utilise sur mes projets depuis un bon moment maintenant. C'est vraiment pratique.

0

Meilleure solution ici;

Dictionary<int, string> userListDictionary = new Dictionary<int, string>(); 
     foreach (var user in users) 
     { 
      userListDictionary.Add(user.Id,user.Name); 
     } 

     cmbUser.DataSource = new BindingSource(userListDictionary, null); 
     cmbUser.DisplayMember = "Value"; 
     cmbUser.ValueMember = "Key"; 

retreive données

MessageBox.Show(cmbUser.SelectedValue.ToString()); 
Questions connexes