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
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.
Combobox.Text geht nicht, weil er mir das zusammengesetze bei Auswahl eines aus der Liste ausgibt (comboBox2.DisplayMember = "FullName";)
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.
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..
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
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)
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)
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.