ComboBox: Hinzufügen von Text und Wert zu einem Element (keine Bindungsquelle)

202

Wie kann ich in C # WinApp den Elementen meiner ComboBox sowohl Text als auch Wert hinzufügen? Ich habe eine Suche durchgeführt und normalerweise verwenden die Antworten "An eine Quelle binden". In meinem Fall ist jedoch keine Bindungsquelle in meinem Programm bereit. Wie kann ich so etwas tun:

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

Antworten:

361

Sie müssen Ihren eigenen Klassentyp erstellen und die ToString () -Methode überschreiben, um den gewünschten Text zurückzugeben. Hier ist ein einfaches Beispiel für eine Klasse, die Sie verwenden können:

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

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

Das Folgende ist ein einfaches Beispiel für seine Verwendung:

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
quelle
4
Brauchen wir wirklich diese neue Klasse ComboboxItem? Ich denke, es gibt bereits eine namens ListItem.
Amr Elgarhy
15
Ich glaube, dass dies möglicherweise nur in ASP.NET und nicht in WinForms verfügbar ist.
Adam Markowitz
1
Nein. Das Element ist ein separater Typ, der nur zum Speichern der Daten der Elemente (Text, Wert, Verweise auf andere Objekte usw.) verwendet wird. Es ist kein Nachkomme einer ComboBox und es wäre äußerst selten, dass dies der Fall wäre.
Adam Markowitz
1
Ich weiß, dass ich etwas spät zur Party komme, aber wie ich dies in einer reinen Windows-Formularumgebung tat, bestand darin, eine Datentabelle einzurichten, Elemente hinzuzufügen und die Combobox an die Datentabelle zu binden. Man würde denken, dass es eine sauberere Methode geben sollte, aber ich habe keine gefunden (DisplayMember ist die Eigenschaft in der Combobox, die für die Anzeige von Text gewünscht wird, ValueMember für den Wert der Daten)
user2366842
4
Wie bekommen wir "SelectedValue" oder wählen den Artikel basierend auf dem Wert aus ... bitte antworten Sie
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;
fabelhaft
quelle
2
Funktioniert perfekt und dies sollte die ausgewählte Antwort sein. Aber können wir nicht comboBox1.SelectedText verwenden, anstatt .SelectedItem zu konvertieren und .Value zu nehmen?
Jeffrey Goines
@fab wie finden Sie Artikel in der Combobox mit einem bestimmten Schlüssel
Smith
Ist es möglich, ein Element in der Combobox basierend auf dem Wörterbuchschlüssel auszuwählen? Wählen Sie wie Taste 3, damit Element mit Taste 3 ausgewählt wird.
Dror
Diese Methode funktioniert nicht mehr für vs2015. Ausnahmen, die darüber geworfen wurden, dass es nicht möglich ist, sich an ein neues Ausstellungsmitglied und Valuemember zu binden
Plater
119

Sie können eine anonyme Klasse wie folgt verwenden:

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

UPDATE: Obwohl der obige Code im Kombinationsfeld ordnungsgemäß angezeigt wird, können Sie ihn nicht verwenden SelectedValueoder SelectedTextEigenschaften von ComboBox. Um diese verwenden zu können, binden Sie das Kombinationsfeld wie folgt:

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
quelle
14
Ich möchte dies leicht ändern, da ein Programmierer wahrscheinlich eine for-Schleife dazu benötigt. Anstelle eines Arrays habe ich eine Liste verwendet. List<Object> items = new List<Object>(); Dann konnte ich die Methode items.Add( new { Text = "report A", Value = "reportA" } );innerhalb der Schleife verwenden.
Andrew
1
Andrew, hast du die Liste <Objekt> dazu gebracht, mit der SelectedValue-Eigenschaft zu arbeiten?
Peter PitLock
@ Venkat,comboBox.SelectedItem.GetType().GetProperty("Value").GetValue(comboBox.SelectedItem, null)
Optavius
2
@Venkat Wenn Sie die zweite Lösung verwenden, mit der festgelegt wird DataSource, können Sie die SelectedValueoder SelectedText-Eigenschaften der Combobox verwenden, sodass kein spezielles Casting erforderlich ist.
JPProgrammer
32

Sie sollten dynamicobject verwenden, um das Combobox-Element zur Laufzeit aufzulösen.

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

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

(comboBox.SelectedItem as dynamic).Value
Mert Cingoz
quelle
1
Dies ist viel besser als das Erstellen einer separaten Klasse und das Überschreiben von ToString ().
Don Shrout
1
Dynamic ist nur in C # 4 und höher verfügbar. (.NET 4.5, denke ich)
MickeyfAgain_BeforeExitOfSO
Einfach und schneller zu schreiben! Ich habe dies für SelectedValue in VB.net getan: Dim Value As String = CType (Me.SectionIDToComboBox.SelectedItem, Object) .Value
Hannington Mambo
1
Wie kann man dann mit dem "Wert" das richtige Kombinationsfeld einstellen?
Dave Ludwig
17

Sie können DictionaryObject verwenden, anstatt eine benutzerdefinierte Klasse zum Hinzufügen von Text und Wert in a zu erstellen Combobox.

Hinzufügen von Schlüsseln und Werten in einem DictionaryObjekt:

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

Binden Sie das Quellwörterbuchobjekt an Combobox:

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

Schlüssel und Wert abrufen:

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

Vollständige Quelle: Combobox Text nd Wert

cronynaval
quelle
14

Dies ist einer der Wege, die mir gerade in den Sinn gekommen sind:

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

Und um den Text oder den Wert eines Elements zu ändern, können Sie dies folgendermaßen tun:

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

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

In Windows Forms gibt es keine Klasse namens ListItem . Es existiert nur in ASP.NET , daher müssen Sie Ihre eigene Klasse schreiben, bevor Sie es verwenden können, genau wie @Adam Markowitz in seiner Antwort .

Überprüfen Sie auch diese Seiten, sie können helfen:

Amr Elgarhy
quelle
2
Sofern ich mich nicht irre, ist ListItem nur in ASP.NET verfügbar
Adam Markowitz
ja :( leider ist es nur in ASP.net ... also was kann ich jetzt tun?
Bohn
Wozu dienen dann die Eigenschaften SelectedValue oder SelectedText in einer Combobox?
JSON
11

Ich weiß nicht, ob dies für die im ursprünglichen Beitrag angegebene Situation funktioniert (egal, dass dies zwei Jahre später ist), aber dieses Beispiel funktioniert für mich:

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

Um Ihren Wert wieder auszulesen, müssen Sie die SelectedItem-Eigenschaft in ein DictionaryEntry-Objekt umwandeln, und Sie können dann die Schlüssel- und Werteigenschaften davon auswerten. Zum Beispiel:

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

Wenn sich noch jemand dafür interessiert, finden Sie hier eine einfache und flexible Klasse für ein Combobox-Element mit einem Text und einem Wert eines beliebigen Typs (sehr ähnlich dem Beispiel von 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;
    }
}

Die Verwendung von <T>ist besser als die Deklaration von valueals object, da objectSie dann den Typ verfolgen müssen, den Sie für jedes Element verwendet haben, und ihn in Ihren Code umwandeln müssen, um ihn ordnungsgemäß zu verwenden.

Ich benutze es jetzt schon eine ganze Weile für meine Projekte. Es ist wirklich praktisch.

Matheus Rocha
quelle
4

Ich mochte die Antwort von fab, wollte aber kein Wörterbuch für meine Situation verwenden, also ersetzte ich eine Liste von Tupeln.

// 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
quelle
3

Ein Beispiel mit 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
quelle
3

Mit diesem Code können Sie einige Elemente in ein Kombinationsfeld mit Text und Wert einfügen.

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
quelle
Bitte erläutern Sie Ihre Lösung.
Vaibhav Bajaj
Fügen Sie einfach die folgenden Länder in ihren jeweiligen Indizes in eine Combox ein. Wenn Sie sie ausführen. Eine Combox wird mit einer Option angezeigt, die sich im Index 0 befindet. Wenn Sie auf die Combox klicken, wird die andere folgende Option
Muhammad Ahmad
Dies funktioniert nicht für IDs. Dies ist lediglich eine Möglichkeit, die Liste zu indizieren
. Darum ging es
2

Neben der Antwort von Adam Markowitz gibt es hier eine allgemeine Möglichkeit, die ItemSourceWerte einer Combobox (relativ) einfach festzulegen enums, während dem Benutzer das Attribut 'Description' angezeigt wird. (Man könnte meinen, jeder würde dies tun wollen, damit es sich um einen .NET- Einzeiler handelt, aber das ist es einfach nicht, und dies ist der eleganteste Weg, den ich gefunden habe).

Erstellen Sie zunächst diese einfache Klasse, um einen beliebigen Enum-Wert in ein ComboBox-Element zu konvertieren:

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

Zweitens müssen Sie in Ihrem OnLoadEreignishandler festlegen, dass die Quelle Ihres Kombinationsfelds eine Liste ist, ComboEnumItemsdie auf jedem Enumin Ihrem EnumTyp basiert . Dies kann mit Linq erreicht werden. Dann stellen Sie einfach Folgendes ein 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";
    }

Jetzt wählt der Benutzer aus einer Liste Ihrer Benutzerfreundlichen aus Descriptions, aber was er auswählt, ist der enumWert, den Sie im Code verwenden können. Um auf die Auswahl des Benutzers im Code zuzugreifen, comboBoxUserReadable.SelectedItemwird das ComboEnumItemund comboBoxUserReadable.SelectedValuedas sein EMyEnum.

Bill Pascoe
quelle
1

Sie können einen generischen Typ verwenden:

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

Beispiel für die Verwendung eines einfachen int-Typs:

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
quelle
0

Ich hatte das gleiche Problem. Ich habe einen neuen hinzugefügt, der ComboBoxnur den Wert im selben Index enthält wie den ersten. Wenn ich dann die Hauptkombination ändere, ändert sich der Index im zweiten Index zur gleichen Zeit, und dann nehme ich den Wert der zweiten Combo und benutze es.

Dies ist der 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
quelle
0

Klassenerstellung:

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

Form1-Codes:

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

        }

    }
}
Grenzenlose isa
quelle
0

So macht es Visual Studio 2013:

Einzelexemplar:

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

Mehrere Artikel:

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

Keine Notwendigkeit, Klassenüberschreibungen durchzuführen oder etwas anderes einzuschließen. Und ja die comboBox1->SelectedItemund comboBox1->SelectedIndexAnrufe funktionieren noch.

Rätsel
quelle
0

Dies ähnelt einigen anderen Antworten, ist jedoch kompakt und vermeidet die Konvertierung in ein Wörterbuch, wenn Sie bereits eine Liste haben.

Wenn eine ComboBox"Combobox" in einem Windows-Formular und eine Klasse SomeClassmit der stringtype-Eigenschaft angegeben sind Name,

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

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

Dies bedeutet, dass das SelectedItem ein SomeClassObjekt von listist und jedes Element in comboboxunter seinem Namen angezeigt wird.

Alex Smith
quelle
Wahr! Ich habe DisplayMembervorher benutzt ... Ich vergesse immer, dass es existiert. Ich habe mich an die Lösung gewöhnt, die ich gefunden habe, bevor ich auf diese Eigenschaft geachtet habe, auch wird es nicht immer helfen. Nicht alle Klassen haben eine Nameoder Tag-Eigenschaft oder eine Zeichenfolge-Eigenschaft, die beliebig als Anzeigetext verwendet werden kann.
Matheus Rocha
Das ist ein guter Punkt. Wenn Sie die Klasse ändern können, lohnt es sich möglicherweise, der Klasse eine solche Eigenschaft hinzuzufügen, z. B. eine Eigenschaft 'ComboBoxText' (die die ToString () -Methode zurückgeben könnte, falls verfügbar). Wenn die Klasse nicht geändert werden kann, kann alternativ möglicherweise eine abgeleitete Klasse erstellt werden, in der die Eigenschaft 'ComboBoxText' implementiert werden kann. Dies wäre nur dann sinnvoll, wenn Sie die Klasse mehrmals zu einer ComboBox hinzufügen müssen. Andernfalls ist es einfacher, nur ein Wörterbuch zu verwenden, wie in einer der anderen Antworten erläutert.
Alex Smith
Hey Alex, ich habe eine Antwort mit der Methode gegeben, die ich normalerweise in diesen Fällen verwende. Ich denke, es ist ziemlich nah an dem, was du gesagt hast, oder vielleicht habe ich nicht verstanden, was du gesagt hast. Ich habe mich nicht von der Klasse abgeleitet, da Sie in einigen Klassen möglicherweise Methoden implementieren müssen, die wir nicht überschreiben möchten (wir hätten also eine Reihe von Methoden mit einer einfachen base.Method();). Außerdem müssten Sie eine abgeleitete Klasse erstellen für jeden unterschiedlichen Typ, den Sie zu Kombinationsfeldern oder Listenfeldern hinzufügen möchten. Die Klasse, die ich gemacht habe, ist flexibel und kann mit jedem Typ ohne zusätzlichen Aufwand verwendet werden. Schauen Sie unten nach meiner Antwort und sagen Sie mir, was Sie denken :)
Matheus Rocha
Ich stimme zu, Ihre Antwort scheint definitiv bequemer zu sein, als eine abgeleitete Klasse für jeden Typ zu erstellen, den Sie einer Combobox hinzufügen möchten. Gut gemacht! Ich denke in Zukunft, wenn ich keine Eigenschaft wie 'Name' zur Verfügung habe, werde ich so etwas wie Ihre Antwort oder die Wörterbuchantwort verwenden :)
Alex Smith
0

Dies ist eine sehr einfache Lösung für Windows-Formulare, wenn nur der Endwert als (Zeichenfolge) benötigt wird. Die Namen der Elemente werden im Kombinationsfeld angezeigt und der ausgewählte Wert kann leicht verglichen werden.

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;

und im Ereignishandler den Wert (String) des ausgewählten Werts abrufen

string test = testComboBox.SelectedValue.ToString();
Esteban Verbel
quelle
0

Bessere Lösung hier;

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

Daten abrufen

MessageBox.Show(cmbUser.SelectedValue.ToString());
Orhan Bayram
quelle
Während ich die Combobox füllen konnte, führt das Klicken darauf zu diesem Fehler in VS2019. Ein QueryInterface-Aufruf wurde durchgeführt, um die Klassenschnittstelle der COM-sichtbaren verwalteten Klasse 'ComboBoxUiaProvider
MC9000