Combox mit Text und Id befüllen zwecks ID Rückschreiben in DB



  • Hallo,

    ich fülle eine Dropdownbox aus der Datenbank:

    SqlCommand sqlComm = new SqlCommand("SELECT Name FROM Laender", sqlConn);
                    myReader = sqlComm.ExecuteReader();
                    while (myReader.Read())
                    {
                        Land.Items.Add(myReader["Name"]);
                    }
                    sqlConn.Close();
    

    Somit habe ich nun in meiner Dropdownbox alle Länder die in der Tabelle stehen.
    Nun wählt der Benutzer ein Land aus. Die Länder haben im Übrigen eine autoinkrementelle ID. Nun wird diese Auswahl zurück in eine andere Datenbank geschrieben. Dort möchte ich jetzt aber nicht den Namen des Landes sondern die ID des Landes reinschreiben. Im Sinne der relationellen DB sollte das so sein, dass ich später eindeuttig auf diese ID selektieren kann. Ala: Zeige mir alle Einträge in der Gästetabelle Where ID = 1, also Land beispielsweise Deutschland.

    Nun meine Frage: Ich weiss nicht wie ich es anstelle, dass ich die ID in eine DB zurückschreiben kann, da die Eigenschaft Items ja schon mit "Ländername" belegt ist. Der Benutzer sieht den Ländernamen, ich muss aber die ID des gewählten Landes rückschreiben !?!!! Ich will auch nicht die ID Vorne anhängen, oder gar hinterher, also nach der Auswahl nochmal die ID aus der DB ziehen. Wennn dann einer einen Ländernamen doppelt anlegt, hat das Land schon zwei Ids!!!

    Danke für Eure Ideen!

    MaPe



  • Hallo,

    da gibt es verschiedene Lösungen. Generell lautet das Stichwort aber "DataBinding".

    Die einfachste wäre, du erstellst dir eine eigene Klasse

    class Country
    {
      public int Id { get; set; }
      public string Name { get; set; }
    }
    

    Zum Anzeigen kannst du entweder die ToString()-Methode überschreiben:

    public override void ToString()
    {
      return Name;
    }
    

    oder aber als "DisplayMember" dann "Name" angeben:

    comboBox.DisplayMember = "Name";
    

    Und mittels "ValueMember" kannst du dann die "Id" angeben (welche du dann mittels SelectedValue wieder ermitteln kannst):

    comboBox.ValueMember = "Id";
    

    Schau dir in der Hilfe am besten diese Eigenschaften an (und zusätzlich noch "SelectedIndex", "SelectedItem", "SelectedValue")...

    Nun mußt du eine Liste mit diesen Ländern erstellen und dann der CombBox zuweisen:

    List<Country> list = new List<Country>();
    
    // in Schleife
    Country c = new Country();
    c.Id = (int)myReader["Id"];
    c.Name = myReader["Name"].ToString();
    list.Add(c);
    
    // zuletzt
    comboBox.DataSource = list;
    

    Und die andere Lösung wäre, du füllst deine Daten in eine DataTable (mittels eines DataAdapters und dessen Fill()-Methode) und weist diese dann der ComboBox als Datenquelle hinzu:

    comboBox.DisplayMember = "Id";
    comboBox.ValueMember = "Name";
    comboBox.DataSource = dataTable; // <- immer als letztes zuweisen
    

    DataBinding ist jedoch ein umfangreiches Thema, mit dem du dich aber beschäftigen solltest (so daß du letztenendes weniger zu programmieren hast 😉

    Einstieg, s. mein Beitrag http://www.c-plusplus.net/forum/p2049983#2049983 (sowie mein zweiter Beitrag dadrin etwas weiter unten)



  • Erstmal herzlichen Dank für Deinen tollen Beitrag!
    Ich habe mich für das entschieden:

    List<Country> list = new List<Country>();
                    while (myReader.Read())
                    {
    
                        Country c = new Country();
                        c.ID = (int) myReader["ID"];
                        c.Name = myReader["Name"].ToString();
                        list.Add(c);
    
                    }
                   Land.DataSource = list;
    
    1. Er füllt nun die Box, aber allerdings steht immer Windowsformapplication1.country drin.
    2. Geht das nur wenn ich die Zeile c.ID = (int) myReader["ID"]; auskommentiere,
      wenn ich die drinnen lasen, sagt mit mein Fehlerfänger: Die angegebene Umwandlung ist ungültig.

    Hast mir da zwei Ideen?

    Danke MaPe



  • ok ich habs; aber mit einem Fragezeichen.

    ...
    myReader = sqlComm.ExecuteReader();
                    List<Country> list = new List<Country>();
                    while (myReader.Read())
                    {
                        Country c = new Country();
                        c.ID = myReader["ID"].ToString();
                        c.Name = myReader["Name"].ToString();
                        list.Add(c);
                        Land.DisplayMember = "Name";
                        Land.ValueMember = "ID";                               
                    }
                    Land.DataSource = list;
                    sqlConn.Close();
    

    Aufrufen kann ich das ganze nun mit.

    MessageBox.Show(Land.SelectedValue.ToString());
    

    ...und dann entsprechend in die DB in einen Datensatz packen.

    Ich musste in Deiner Methode das int bei ID auf String setzen,

    class Country
        {
            public string ID { get; set; }
            public string Name { get; set; }
        }
    

    und dann den Wert vor dem Rückschreiben in die DB wieder ToSting() machen.
    Schön wäre es jetzt noch zu wissen, warum ich das int nicht in die List schreiben konnte. Ich würde gerne wissen warum das nicht ging.
    Nimmt der Datasource hier nur Strings auf *schulterzuck* ....?

    Stehe da etwas auf dem Schauch....

    Danke MaPe



  • Hallo,

    bei der "ID" bin ich natürlich davon ausgegangen, daß diese auch in der Datenbank als "Ganzzahl" (integer) abgelegt ist - und dann müßte auch der "cast" mittels (int) klappen.
    Ansonsten kannst du mal den Datentyp dir mittels

    object o = myReader["ID"];
    string typeName = o.GetType().FullName;
    

    ausgeben lassen (am besten einfach direkt im Debugger dir anschauen).
    Müßte eigentlich "System.Int32" (d.h. 'int') sein.
    Schreib einfach mal zurück, welcher 'typeName' bei dir für die Spalte "ID" herauskommt.

    Und zum Auslesen mußt du dann auch wieder in den entsprechenden Datentypen casten, d.h.

    int id = (int)comboBox.SelectedValue;
    

    Nun kannst du dann wieder normal mit dieser Id arbeiten.

    Und den gesamten Datensatz erhältst du mittels

    Country c = comboBox.SelectedItem as Country;
    

    (das Schlüsselwort 'as' sollte man immer für alle Referenztypen (class) verwenden, denn so kann man überprüfen, ob die Umwandlung wirklich korrekt war. Denn wenn nicht, dann wird 'null' zurückgegeben, auf das man dann mittels "if (c != null)" testen kann).

    P.S: Die Zuweisung an Display- und ValueMember brauchst du nur einmalig zu machen, d.h. nach der Schleife:

    Land.DisplayMember = "Name";
    Land.ValueMember = "ID";
    Land.DataSource = list;
    

    Und vllt. hatte ich mich bei der ToString-Methode etwas mißverständlich ausgedrückt. Diese bezog sich auf die Country-Klasse, d.h.

    class Country
    {
      public int Id { get; set; }
      public string Name { get; set; }
    
      public override void ToString()
      {
        return Name;
      }
    }
    

    (aber wie schon geschrieben, dies ist alternativ zur Angabe der expliziten DisplayMember-Eigenschaft).



  • Dankesehr für diese tolle und professionelle Hilfe. MaPe


Anmelden zum Antworten