Laden...

Combobox Valuemember mit zusammengefügtem Displaymember ist "null" beim Abrufen

Erstellt von Torni vor 6 Jahren Letzter Beitrag vor 6 Jahren 2.108 Views
T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 6 Jahren
Combobox Valuemember mit zusammengefügtem Displaymember ist "null" beim Abrufen

Hi,

ich lese Daten einer Textdatei in ne List.
Diese wird mittels DataBinding an ne Combo "gehängt".


        {
            var lines2 = File.ReadLines(@"mc.txt",Encoding.Default);
            var data2 = lines2.Select(l2 => l2.Split(';'));

            List<MCB> alleMC = data2
                .Where(arr2 => arr2.Length >= 2)
                .Select(arr2 => new MCB
                {
                    Ort = arr2[0],
                    Name2 = arr2[1]
                })
                .ToList();

            var bindingSourceMC = new BindingSource();
            bindingSourceMC.DataSource = alleMC;
            comboBox2.DataSource = bindingSourceMC.DataSource;
            comboBox2.ValueMember = "Ort";
            comboBox2.DisplayMember = "FullName";

        }

mittels


    public class MCB
    {
        public string Name2 { get; set; }
        public string Ort { get; set; }
        public string FullName
        {
            get { return Ort + " " + Name2; }
        }
    }

setze ich für den Text in der Combo beide zusammen.

Mit comboBox2.SelectedValue.ToString()) bekomme ich den Wert, wenn ich die Combo als **DropDownList **definiere. (werden per Button ausgelesen und dann weiterverarbeitet)
Da ich aber auch Werte direkt in die Combo eingeben (also als "normale" DropDown definiert) möchte, funktioniert das nicht.
Fehlermeldung dann bei eingegeben Wert:

Fehlermeldung:
System.NullReferenceException: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

Stehe grad aufm Schlauch..

edit: Typo

C
2.121 Beiträge seit 2010
vor 6 Jahren

ToString ist nicht ratsam. Das gibt dir immer irgendwas zurück, außer das Objekt ist null. Immer "irgendetwas" ist Unsinn.
In deinem Fall ist SelectedValue null weil bei einem frei eingegebenen Wert nichts vorgegebenes selektiert ist.
Lese direkt Combobox.Text aus.

T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 6 Jahren

Combobox.Text geht nicht, weil er mir das zusammengesetze bei Auswahl eines aus der Liste ausgibt (comboBox2.DisplayMember = "FullName";)

C
2.121 Beiträge seit 2010
vor 6 Jahren

Was soll es denn ausgeben wenn du nichts selektiert sondern Text von Hand eingegeben hast?
Dann unterscheide doch ob SelectedValue gesetzt ist oder nicht und nimm dann entweder .Text oder den SelectedValue.
Oder ich hab das noch nicht verstanden, dann erklär am besten nochmal was du vorhast.

T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 6 Jahren

ja wie unterscheidet man dies??

wenn ich was eingebe will ich das eingegebene haben und wenn ich selektiere das eben..

da steh ich ja grad quer aufm schlauch..

5.658 Beiträge seit 2006
vor 6 Jahren

Hi Torni,


comboBox2.ValueMember = "Ort";

...ist auch komisch. Kannst du ausschließen, daß mehrere Namen den gleichen Ort verwenden? Eigentlich sollte man die SelectedItem-Eigenschaft verwenden.

In [Artikel] MVVM und DataBinding gibt es auch ein ListView-Beispiel, das du so einfach auf eine ComboBox übertragen kannst.

Weeks of programming can save you hours of planning

3.003 Beiträge seit 2006
vor 6 Jahren

Dein Problem ist dein Databinding. Wenn in die CB ein neuer Wert eingetragen wird, musst du:

a) eine neue Instanz der Klasse MCB erstellen
b) sie der DataSource hinzufügen
c) evtl neu binden

WinForms weiß, dass es an Objekte vom Typ "MCB" gebunden ist, dass SelectedValue die Eigenschaft "Ort" des gebundenen Elements ist, und dass die Eigenschaft "FullName" des gebundenen Elements benutzt wird, um den Text darzustellen. Deshalb geht MrSparkles Anmerkung in die falsche Richtung, die Ort-Eigenschaft muss nicht eindeutig sein, weil die Elemente der ComboBox vom Typ MCB sind und als Referenzen immer eindeutig sind, auch wenn ihre Eigenschaften gleich sind. SelectedItem ist dann übrigens die selektierte jeweilige MCB-Instanz.

Was die Combobox NICHT weiß, ist, wie es aus einer Texteingabe eine Instanz von MCB erzeugt werden soll. Das solltest du ihm beibringen, indem du dich in den Prozess des Neueinfügens hängst.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

3.003 Beiträge seit 2006
vor 6 Jahren

Sehr, sehr rudimentäre Variante:


const char SPLIT_CHAR = ';';

var mcbList = File.ReadLines(@"mc.txt", Encoding.Default)
    .Select(p => p.Split(SPLIT_CHAR))
    .Where(p => p.Length == 2)
    .Select(Mcb.Create)
    .ToList();

var bindingSourceMc = new BindingSource {DataSource = mcbList};
comboBox1.DataSource = bindingSourceMc.DataSource;
comboBox1.ValueMember = "Ort";
comboBox1.DisplayMember = "FullName";

comboBox1.LostFocus += (sender, args) => //nicht das beste Event dafür, aber ist ja nur Demo :)
{
    var cb = sender as ComboBox;
    if(cb == null) return;
    if (cb.SelectedItem == null)
    {
        var newItem = Mcb.Create(cb.Text.Split(' '));

        bindingSourceMc.Add(newItem);
        comboBox1.DataSource = bindingSourceMc;
        comboBox1.SelectedItem = newItem;
    }

    MessageBox.Show(cb.SelectedValue.ToString(), @"Debug ;)");
};

//Bequemlichkeitsänderungen an MCB
public class Mcb
{
    private Mcb() { }
    private string Name2 { get; set; }
    public string Ort { get; private set; }
    public string FullName => $"{Ort} {Name2}";

    public static Mcb Create(string[] init)
    {
        return new Mcb
        {
            Ort = init[0],
            Name2 = init[1]
        };
    }
}

EDIT: Schönheitskorrektur

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

T
Torni Themenstarter:in
50 Beiträge seit 2014
vor 6 Jahren

Hallo LaTino,

vielen Dank für diesen Denkanstoß.
Werde ich mir zur Gemüte führen.

Kurzfristig hatte ich eine Quick'nDirty-Variante getestet in dem ich einfach per try/catch den String in der combo.text nach dem Leerzeichen (Aufbau ist immer gleich) abgeschnitten hatte und im catch halt wenn kein Leerzeichen, dann dies übernahm..

War nicht schön aber hatte auf die schnelle funktioniert, zumindest bis ich ne elegante Lösung finde.