ComboBox mit Objekten füllen und ToString() Dynamisch anpassen

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Pardasus.

    ComboBox mit Objekten füllen und ToString() Dynamisch anpassen

    Moin,
    ich brauche mal Hilfe bei der Umsetzung. Ich hoffe es richtig erklären zu können was ich vorhabe.

    1. TextBox => hier wird ein Suchbegriff eingegeben
    2. ComboBox => hier werden die Ergebnisse Ausgegeben

    Hier mal ein Beispiel wie das in etwas aussieht

    C#-Quellcode

    1. using System.Collections.Generic;
    2. using System.Linq;
    3. using System.Text.RegularExpressions;
    4. using System.Windows.Forms;
    5. namespace Beispiel
    6. {
    7. public partial class Form1 : Form
    8. {
    9. Database database = new Database();
    10. public Form1()
    11. {
    12. InitializeComponent();
    13. comboBox1.Items.AddRange(database.GetCustomers().ToArray());
    14. textBox1.KeyDown += TextBox1_KeyDown;
    15. }
    16. private void TextBox1_KeyDown(object sender, KeyEventArgs e)
    17. {
    18. comboBox1.Items.Clear();
    19. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Firstname, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    20. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Lastname, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    21. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Street, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    22. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Location, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    23. }
    24. }
    25. public class Database
    26. {
    27. List<Customer> customers;
    28. public Database()
    29. {
    30. customers = new List<Customer>()
    31. {
    32. new Customer() { Firstname = "Max", Lastname = "Müller", Street = "Beispielstr. 1", Location = "Local eben" },
    33. new Customer() { Firstname = "Mustermann", Lastname = "Meyer", Street = "Musterstrasse 5", Location = "Beispielstadt" },
    34. new Customer() { Firstname = "Beispiel", Lastname = "Schultz", Street = "Irgendwo 11", Location = "Erde" }
    35. };
    36. }
    37. public IEnumerable<Customer> GetCustomers()
    38. {
    39. foreach (var customer in customers)
    40. {
    41. yield return customer;
    42. }
    43. }
    44. }
    45. public class Customer
    46. {
    47. private string firstname = "";
    48. public string Firstname
    49. {
    50. get { return firstname; }
    51. set { firstname = value; }
    52. }
    53. private string lastname = "";
    54. public string Lastname
    55. {
    56. get { return lastname; }
    57. set { lastname = value; }
    58. }
    59. private string street = "";
    60. public string Street
    61. {
    62. get { return street; }
    63. set { street = value; }
    64. }
    65. private string location = "";
    66. public string Location
    67. {
    68. get { return location; }
    69. set { location = value; }
    70. }
    71. public override string ToString()
    72. {
    73. return firstname + " " + lastname;
    74. }
    75. }
    76. }


    Erklärung:
    Es wird ein Text eingeben und bei jeden Tastendruck wird die "Datenbank" durchsucht mit Hilfe von RegEx. Sobald er ein Treffer hat, Packt er das Objekt "Customer" in die ComboBox.
    ToString() habe ich überschrieben damit in der ComboBox auch was sinniges steht. Wenn man nun etwas aus der ComboBox auswählt, kann ich das Objekt wieder Casten und damit weiter Arbeiten.

    Mein Problem:
    Es wird immer "Vorname + Nachname" ausgegeben. Wenn ich z.b. "Beisp" in die Textbox eingebe, finde er alles wo diese Zeichenfolge vorkommt.
    Beim "Mustermann" fängt der Ort mit "Beisp" auch an, es wird dann aber auch nur "Vorname + Nachname" ausgeben.
    Ich würde aber gerne, je nachdem wo der Treffer ist, die ToString() Ausgabe anpassen.

    TextBox Eingabe = "Beisp"

    Ergebnis in der ComboBox soll so aussehen:
    - Max Müller (Beispielstr. 1)
    - Mustermann Meyer (Beispielstadt)
    - Beispiel Schultz
    Es soll Grundsätzlich immer

    Vorname + Nachname

    stehen. Aber wenn der Treffen bei z.b. der Stasse ist, soll dort

    Vorname + Nachname (Strasse)

    stehen. Mir ist es nur wichtig, dass in der ComboBox Objecte von Customer stehen, damit ich damit später weiter Arbeiten kann. Wenn man etwas auswählt in der ComboBox habe ich gleich das passende Object von Customer dazu. Darum ja auch das überschreiben von ToString()
    Ich meinte so etwas in der Art.

    Dann bekommst du direkt dass Objekt von der DatabseKlasse und kannst dann je nachdem was stimmt die Funktion anpassen und z.B. einen String zusammenbasteln und diesen zurückgeben. Hab dass jetzt schnell durch den Converter gejagt. Und ein Property der die komplette List of Costumer als Array zurückgibt.

    VB.NET-Quellcode

    1. private Customer GetCustomer(string Search)
    2. {
    3. foreach (Customer c in b.GetCustomers) {
    4. if (c.Firstname.Contains(Search) | c.Lastname.Contains(Search) | c.Location.Contains(Search) | c.Street.Contains(Search)) {
    5. return c;
    6. }
    7. }
    8. return null;
    9. }


    Ach ja, dein RegExMatch musst du wieder einfügen. Hab dass nur schnell mal am Tablet geschrieben.

    #Edit

    Da du die Objekte der Combobox übergibst, können dort logischerweise auch nur die Daten stehen die du bei ToString überschrieben hast.
    Würde mir da etwas anderes überlegen. Und die Daten anders bearbeiten. Eventuell direkt in deiner Database Klasse Funktionen zum überprüfen und ausgeben schreiben. So dass am Ende in deiner Combobox keine Objecte von customer stehen, sondert nur in deiner Klasse Database.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bagplatt“ ()

    Dachte gerade die Löschung zu haben, aber dann doch wieder nicht.

    @Bagplatt danke für deine Ideen, aber komme leider nicht weiter.

    Vielleicht könnte man mit einem Dictonary Arbeiten in der ComboBox?... Ich komme einfach nicht drauf.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Pardasus“ ()

    Pardasus schrieb:

    Mein Problem:
    Es wird immer "Vorname + Nachname" ausgegeben. Wenn ich z.b. "Beisp" in die Textbox eingebe, finde er alles wo diese Zeichenfolge vorkommt.
    Beim "Mustermann" fängt der Ort mit "Beisp" auch an, es wird dann aber auch nur "Vorname + Nachname" ausgeben.
    Ich würde aber gerne, je nachdem wo der Treffer ist, die ToString() Ausgabe anpassen.

    TextBox Eingabe = "Beisp"

    Ergebnis in der ComboBox soll so aussehen:
    - Max Müller (Beispielstr. 1)
    - Mustermann Meyer (Beispielstadt)
    - Beispiel Schultz
    Dein Beispiel widerspricht deiner eigenen Problemspezifikation. Inne PS sagst du, du wollest nur ausgeben, wo der Treffer ist, im Beispiel zeigst du aber immer Nachname, Vorname an, und optional zusätzlich eine weitere Property.

    Imo ist dein Beispiel vernünftiger als deine Problemspezifikation, also korrekte Problemspezifikation wäre: du möchtest immer Name, Vorname anzeigen, und zusätzlich optional noch die Treffer-Property.
    Mit "flexibler Tostring-Überschreibung" geht das nicht - sowas gibts nämlich nicht (doch - wäre sogar machbar, aber echt keine gute Idee).

    Also sollteste entweder der Combo eine benutzerdefinierte Formatierung angedeihen lassen, oder du stattest deine Customer-Klasse mit einer Zusatz-Property DisplayText aus, wo du dann halt reinschreibst, was der Customer grad anzeigen soll.

    Aber ich wäre sehr für eine benutzerdefinierte Formatierung, weil der Anzeige-Wert in Abhängigkeit eines Such-Patterns hat im Daten-Objekt selbst eiglich nix verloren.
    Nutze dafür das Format-Event.
    Du hast es exakt auf den Punkt gebracht! Ich hatte extra das Beispiel mitgeschickt, da ich nicht wusste wie ich es beschreiben soll.
    Du hast es aber Perfekt beschrieben was mein Problem ist.

    Das mit dem Format Event hört sich sehr vielversprechend an. Habe auch gleich mal nach im Netz geschaut. Werde aber leider nicht ganz schlau draus.

    Beispielt aus dem Netz

    C#-Quellcode

    1. private void comboBox1_Format(object sender, ListControlConvertEventArgs e)
    2. {
    3. string Name = ((yourClass)e.ListItem).Property1;
    4. string LastName = ((yourClass)e.ListItem).Property2;
    5. e.Value = Name + " " + LastName;
    6. }


    Also ich verstehe genau was in den Beispielt passiert, nur nicht wie es mich weiter bring. Es irritiert mich das diese "Format" ein Event ist. Was löst es denn aus?
    Die Combobox löst es aus, wenn sie ein Item anzeigt.
    Und da kannst du in e.Value genau hineinschreiben, was sie anzeigen soll. Für das eine ListItem.

    Jo - das zeigt sie dann an.

    Dein Netz-Fundstück ist denkbar schlecht - gibts denn bei MSDN kein Beispiel?

    also besser wäre:

    C#-Quellcode

    1. private void comboBox1_Format(object sender, ListControlConvertEventArgs e)
    2. {
    3. var cust = (Customer)e.ListItem;
    4. var firstName = cust.firstName;
    5. var LastName = cust.Lastname;
    6. var nochwas = iwasGanzDolles(cust);
    7. e.Value = firstName + " " + LastName + "[" + nochwas +"]";
    8. }

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Habe mir das ganze noch einmal angesehen und es nun hin bekommen. Es Funktioniert exakt so wie ich es mir vorgestellt habe. Aber kann das noch jemand schöner umsetzten? ;)

    Im Anhang mal ein Screenshot.

    C#-Quellcode

    1. using System.Collections.Generic;
    2. using System.Linq;
    3. using System.Text.RegularExpressions;
    4. using System.Windows.Forms;
    5. namespace Beispiel
    6. {
    7. public partial class Form1 : Form
    8. {
    9. Database database = new Database();
    10. ComboBoxDisplayTyp comboBoxDisplayTyp = ComboBoxDisplayTyp.Standard;
    11. public Form1()
    12. {
    13. InitializeComponent();
    14. comboBox1.Items.AddRange(database.GetCustomers().ToArray());
    15. textBox1.KeyDown += TextBox1_KeyDown;
    16. comboBox1.Format += ComboBox1_Format;
    17. }
    18. private void ComboBox1_Format(object sender, ListControlConvertEventArgs e)
    19. {
    20. var customerItem = (Customer)e.ListItem;
    21. var display = customerItem.Firstname + " " + customerItem.Lastname;
    22. switch (comboBoxDisplayTyp)
    23. {
    24. case ComboBoxDisplayTyp.Standard:
    25. e.Value = display;
    26. break;
    27. case ComboBoxDisplayTyp.Street:
    28. e.Value = display + " (" + customerItem.Street + ")";
    29. break;
    30. case ComboBoxDisplayTyp.Location:
    31. e.Value = display + " (" + customerItem.Location + ")";
    32. break;
    33. }
    34. }
    35. private void TextBox1_KeyDown(object sender, KeyEventArgs e)
    36. {
    37. comboBox1.Items.Clear();
    38. comboBoxDisplayTyp = ComboBoxDisplayTyp.Standard;
    39. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Firstname, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    40. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Lastname, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    41. comboBoxDisplayTyp = ComboBoxDisplayTyp.Street;
    42. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Street, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    43. comboBoxDisplayTyp = ComboBoxDisplayTyp.Location;
    44. comboBox1.Items.AddRange(database.GetCustomers().Where(arg => Regex.IsMatch(arg.Location, textBox1.Text, RegexOptions.IgnoreCase)).ToArray());
    45. }
    46. }
    47. public class Database
    48. {
    49. List<Customer> customers;
    50. public Database()
    51. {
    52. customers = new List<Customer>()
    53. {
    54. new Customer() { Firstname = "Max", Lastname = "Müller", Street = "Beispielstr. 1", Location = "Local eben" },
    55. new Customer() { Firstname = "Mustermann", Lastname = "Meyer", Street = "Musterstrasse 5", Location = "Beispielstadt" },
    56. new Customer() { Firstname = "Beispiel", Lastname = "Schultz", Street = "Irgendwo 11", Location = "Erde" }
    57. };
    58. }
    59. public IEnumerable<Customer> GetCustomers()
    60. {
    61. foreach (var customer in customers)
    62. {
    63. yield return customer;
    64. }
    65. }
    66. }
    67. public class Customer
    68. {
    69. private string firstname = "";
    70. public string Firstname
    71. {
    72. get { return firstname; }
    73. set { firstname = value; }
    74. }
    75. private string lastname = "";
    76. public string Lastname
    77. {
    78. get { return lastname; }
    79. set { lastname = value; }
    80. }
    81. private string street = "";
    82. public string Street
    83. {
    84. get { return street; }
    85. set { street = value; }
    86. }
    87. private string location = "";
    88. public string Location
    89. {
    90. get { return location; }
    91. set { location = value; }
    92. }
    93. }
    94. public enum ComboBoxDisplayTyp
    95. {
    96. Standard,
    97. Street,
    98. Location
    99. }
    100. }
    Bilder
    • 2017-06-26_2006.png

      5,32 kB, 487×293, 110 mal angesehen