ComboBox: ajout de texte et de valeur à un élément (pas de source de liaison)

202

Dans C # WinApp, comment puis-je ajouter du texte et de la valeur aux éléments de mon ComboBox? J'ai fait une recherche et généralement les réponses utilisent "Liaison à une source" .. mais dans mon cas, je n'ai pas de source de liaison prête dans mon programme ... Comment puis-je faire quelque chose comme ça:

combo1.Item[1] = "DisplayText";
combo1.Item[1].Value = "useful Value"
Bohn
la source

Réponses:

361

Vous devez créer votre propre type de classe et remplacer la méthode ToString () pour renvoyer le texte souhaité. Voici un exemple simple d'une classe que vous pouvez utiliser:

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

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

Voici un exemple simple 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());
}
Adam Markowitz
la source
4
avons-nous vraiment besoin de cette nouvelle classe ComboboxItem? je pense qu'il existe déjà un appelé ListItem.
Amr Elgarhy
15
Je crois que cela ne peut être disponible que dans ASP.NET et non dans WinForms.
Adam Markowitz
1
Non. L'élément est un type distinct qui est uniquement utilisé pour stocker les données des éléments (texte, valeur, références à d'autres objets, etc.). Ce n'est pas un descendant d'un ComboBox et il serait extrêmement rare qu'il le soit.
Adam Markowitz
1
Je sais que je suis un peu en retard à la fête, mais comment j'ai fait cela dans un environnement de formulaire Windows pur était de configurer une table de données, d'y ajouter des éléments et de lier la zone de liste déroulante à la table de données. On pourrait penser qu'il devrait y avoir une façon plus propre de le faire, mais je n'en ai pas trouvé un (DisplayMember est la propriété de la zone de liste déroulante que vous voulez pour le texte apparaissant, ValueMember pour la valeur des données)
user2366842
4
comment obtenir "SelectedValue" ou sélectionner l'article en fonction de la valeur ... veuillez répondre
Alpha Gabriel V. Timbol
185
// 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;
fab
la source
2
Fonctionne parfaitement et cela devrait être la réponse choisie. Mais ne pouvons-nous pas utiliser comboBox1.SelectedText au lieu de caster .SelectedItem et prendre .Value?
Jeffrey Goines
@fab comment trouvez-vous un élément dans la zone de liste déroulante avec une certaine clé
Smith
Est-il possible de sélectionner un élément dans la zone de liste déroulante en fonction de la clé de dictionnaire? comme sélectionner la clé 3 pour que l'élément avec la clé 3 soit sélectionné.
Dror
Cette méthode ne fonctionne plus pour vs2015. Exceptions levées de ne pas pouvoir se lier aux nouveaux membres display et valuemember
Plater
119

Vous pouvez utiliser une classe anonyme comme celle-ci:

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 s'affiche correctement dans la zone de liste déroulante, vous ne pourrez pas utiliser SelectedValueni les SelectedTextpropriétés de ComboBox. Pour pouvoir les utiliser, liez la zone de liste déroulante 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;
buhtla
la source
14
Je voudrais modifier cela légèrement parce qu'un programmeur aura probablement besoin d'une boucle for avec cela. Au lieu d'un tableau, j'ai utilisé une liste. List<Object> items = new List<Object>(); J'ai ensuite pu utiliser la méthode items.Add( new { Text = "report A", Value = "reportA" } );dans la boucle.
Andrew
1
Andrew, avez-vous réussi à faire fonctionner List <Object> avec la propriété SelectedValue?
Peter PitLock
@Venkat,comboBox.SelectedItem.GetType().GetProperty("Value").GetValue(comboBox.SelectedItem, null)
Optavius
2
@Venkat si vous utilisez la deuxième solution qui définit le, DataSourcevous pouvez utiliser les propriétés SelectedValueou SelectedTextde la zone de liste déroulante, donc pas besoin de faire de casting spécial.
JPProgrammer
32

Vous devez utiliser dynamicobjet pour résoudre l'élément combobox lors de l'exécution.

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

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

(comboBox.SelectedItem as dynamic).Value
Mert Cingoz
la source
1
C'est bien mieux que de créer une classe distincte et de remplacer ToString ().
Don Shrout
1
dynamique n'est disponible qu'en C # 4 et supérieur. (.NET 4.5 je pense)
MickeyfAgain_BeforeExitOfSO
Simple et plus rapide à écrire! J'ai fait cela pour SelectedValue dans VB.net: Dim Value As String = CType (Me.SectionIDToComboBox.SelectedItem, Object) .Value
Hannington Mambo
1
Comment puis-je définir l'élément de zone de liste déroulante correct en utilisant la "valeur"?
Dave Ludwig
17

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

Ajoutez des clés et des valeurs dans un Dictionaryobjet:

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

Liez l'objet Dictionary source à Combobox:

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

Récupérer la clé et 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

cronynaval
la source
14

C'est l'un des moyens qui viennent à l'esprit:

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

Et pour changer le texte ou la valeur d'un article, 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 , vous devrez donc écrire votre propre classe avant de l'utiliser, comme @Adam Markowitz l'a fait dans sa réponse .

Consultez également ces pages, elles peuvent vous aider:

Amr Elgarhy
la source
2
Sauf erreur, ListItem est uniquement disponible dans ASP.NET
Adam Markowitz
oui :( malheureusement ce n'est que dans ASP.net ... alors que puis-je faire maintenant?
Bohn
Quel est alors l'intérêt des propriétés SelectedValue ou SelectedText dans une zone de liste déroulante?
JSON
11

Je ne sais pas si cela fonctionnera pour la situation donnée dans le message d'origine (sans parler du fait que c'est 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, vous devrez convertir la propriété SelectedItem en un objet DictionaryEntry, puis vous pourrez évaluer les propriétés Key et Value de celui-ci. Par exemple:

DictionaryEntry deImgType = (DictionaryEntry)cmbImageType.SelectedItem;
MessageBox.Show(deImgType.Key + ": " + deImgType.Value);
ChuckG
la source
7
//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);
Ryan
la source
5

Si quelqu'un est toujours intéressé par ceci, voici une classe simple et flexible pour un élément de zone de liste déroulante 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;
    }
}

Il <T>est préférable d' utiliser le que de le déclarer en valuetant que object, car avec objectvous, vous devrez alors garder une trace du type que vous avez utilisé pour chaque élément, et le cast dans votre code pour l'utiliser correctement.

Je l'utilise depuis longtemps sur mes projets. C'est vraiment pratique.

Matheus Rocha
la source
4

J'ai aimé la réponse de fab mais je ne voulais pas utiliser de dictionnaire pour ma situation, j'ai donc substitué 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;
Maggie
la source
3

Un exemple 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();
Soenhay
la source
3

Vous pouvez utiliser ce code pour insérer certains éléments dans une zone de liste déroulante avec du texte et une valeur.

C #

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");   
}

XAML

<ComboBox x:Name="combox" SelectionChanged="ComboBox_SelectionChanged_1"/>
Muhammad Ahmad
la source
Veuillez expliquer votre solution.
Vaibhav Bajaj
Simplement, ajoutez les pays suivants dans leurs index respectifs dans un combox.Lorsque vous l'exécutez. Un combox apparaît avec une option qui est à 0 index.Si vous cliquez sur le combox, l'autre option suivante s'affichera
Muhammad Ahmad
cela ne fonctionne pas pour les identifiants, c'est simplement un moyen d'indexer la liste, ce n'est pas de cela qu'il s'agissait
M. Heelis
2

Suite à la réponse d'Adam Markowitz, voici une manière générale de définir (relativement) simplement les ItemSourcevaleurs d'une zone de liste déroulante enums, tout en montrant l'attribut «Description» à l'utilisateur. (On pourrait penser que tout le monde voudrait le faire pour que ce soit un .NET liner one , mais ce n'est tout simplement pas le cas, et c'est la manière la plus élégante que j'ai trouvée).

Tout d'abord, créez cette classe simple pour convertir n'importe quelle valeur Enum en 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;
    }
}

Deuxièmement, dans votre OnLoadgestionnaire d'événements, vous devez définir la source de votre zone de liste déroulante pour être une liste ComboEnumItemsbasée sur chaque élément Enumde votre Enumtype. Cela peut être réalisé avec Linq. Ensuite, définissez simplement 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 sélectionnera dans une liste de vos utilisateurs Descriptions, mais ce qu'il sélectionnera sera la enumvaleur que vous pouvez utiliser dans le code. Pour accéder à la sélection de l'utilisateur en code, comboBoxUserReadable.SelectedItemsera le ComboEnumItemet comboBoxUserReadable.SelectedValuesera le EMyEnum.

Bill Pascoe
la source
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);
    }
Jan Staecker
la source
0

J'ai eu le même problème, j'ai ajouté un nouveau ComboBox avec juste la valeur dans le même index puis le premier, puis quand je change le combo principal, l'index dans le second change en même temps, alors je prends la valeur du deuxième combo et l'utiliser.

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;
}
Miguel
la source
0

Créateur de classe:

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);

        }

    }
}
Limitless isa
la source
0

Voici comment Visual Studio 2013 le fait:

Un seul 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 remplacer la classe ou d'inclure quoi que ce soit d'autre. Et oui, les appels comboBox1->SelectedItemet comboBox1->SelectedIndexfonctionnent toujours.

Énigme
la source
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.

Étant donné une ComboBox"zone de liste déroulante" sur un formulaire Windows et une classe SomeClassavec la stringpropriété type Name,

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

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

Ce qui signifie que le SelectedItem est un SomeClassobjet de list, et chaque élément dans comboboxsera affiché en utilisant son nom.

Alex Smith
la source
Vrai! J'en ai utilisé DisplayMemberavant ... 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 une propriété Nameou Tag, ou une propriété de chaîne qui pourrait être utilisée arbitrairement comme texte d'affichage.
Matheus Rocha
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 la peine que si vous devez ajouter plusieurs fois la classe à un ComboBox. Sinon, il est plus simple d'utiliser simplement un dictionnaire comme expliqué dans l'une des autres réponses.
Alex Smith
Salut Alex, j'ai fait une réponse avec la méthode 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 ne dérive pas de la classe parce que certaines classes peuvent vous obliger à implémenter des méthodes que nous ne voulons pas remplacer (nous aurions donc un tas de méthodes avec un simple base.Method();), vous devriez également 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 :)
Matheus Rocha
Je suis d'accord, votre réponse semble certainement plus pratique que de créer une classe dérivée pour chaque type que vous souhaitez ajouter à une zone de liste déroulante. Bon travail! Je pense qu'à l'avenir, si je n'ai pas de propriété comme «Nom» facilement disponible, je vais utiliser quelque chose comme votre réponse ou la réponse du dictionnaire :)
Alex Smith
0

Il s'agit d'une solution très simple pour les formulaires Windows si tout ce qui est nécessaire est la valeur finale sous forme de (chaîne). Les noms des éléments seront affichés sur la zone de 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 sur le gestionnaire d'événements obtenir la valeur (chaîne) de la valeur sélectionnée

string test = testComboBox.SelectedValue.ToString();
Esteban Verbel
la source
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";

Récupérer des données

MessageBox.Show(cmbUser.SelectedValue.ToString());
Orhan Bayram
la source
Alors que j'ai pu remplir la zone de liste déroulante, cliquer dessus génère cette erreur dans VS2019 Un appel QueryInterface a été effectué demandant l'interface de classe de la classe gérée visible COM 'ComboBoxUiaProvider
MC9000