| Autor |
Beitrag |
BlackMatrix
      
Beiträge: 243
Erhaltene Danke: 1
|
Verfasst: Mi 11.01.12 23:09
Guten Abend.
Ich meine, das Problem schon einmal ganz einfach gelöst zu haben, aber irgendwie funktioniert es im Moment nicht mehr.
Ich möchte eine Liste meiner Klasse an eine Combobox binden. Dabei möchte ich nicht den Code meiner Klasse ändern, soll heißen, ich möchte keine BindingList in meiner Klasse verwenden. Es soll eine einfache Liste bleiben.
Folgenden Code habe ich:
C#-Quelltext 1: 2:
| bindingSource1.DataSource = Counter.List; listBox1.DataSource = bindingSource1; |
Aber irgendwie funktioniert das nicht. Drücke ich nun einen Button in meiner Winform, die eine Methode des Counterobjekts aufruft und damit die List ändert, dann wird nichts angzeigt.
Was mache ich falsch?
|
|
Th69
      

Beiträge: 4799
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 12.01.12 20:15
Hallo BlackMatrix,
über die BindingSource wird nur die Liste selber überwacht, nicht die Inhalte der Liste (d.h. Änderungen an den Elementen selbst).
Also Einträge zur Liste hinzufügen und aus der Liste löschen sollten sich in der ComboBox widerspiegeln. Hast du jedoch z.B. eine List<Person>, so führt ein Ändern des Personennamens oder der Adresse nicht zu einer Aktualisierung. Dazu müsste die INotifyPropertyChanged-Schnittstelle von deiner Liste implementiert sein, s.a. Gewusst wie: Auslösen von Änderungsbenachrichtigungen mithilfe von "BindingSource" und der "INotifyPropertyChanged"-Schnittstelle.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 12.01.12 21:53
| Zitat: | | Dazu müsste die INotifyPropertyChanged-Schnittstelle von deiner Liste implementiert sein |
Etwas missverständlich du wolltest sagen
| Zitat: | | Dazu müsste die INotifyPropertyChanged-Schnittstelle von den Elementen in deiner Liste implementiert sein |

|
|
Th69
      

Beiträge: 4799
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Fr 13.01.12 10:19
Ja, genau das wollte ich schreiben 
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Fr 13.01.12 12:37
Th69 hat folgendes geschrieben : | | über die BindingSource wird nur die Liste selber überwacht |
Selbst das kann doch nicht funktionieren bei Klassen wie List<>, die eben kein einziges Event besitzen, oder  ?
_________________ >λ=
|
|
BlackMatrix 
      
Beiträge: 243
Erhaltene Danke: 1
|
Verfasst: Fr 13.01.12 14:00
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Fr 13.01.12 14:48
| Zitat: | | Ich meine auch, dass das nicht funktioniert. |
Das ist korrekt. Da die Liste nicht meldet das sie geändert wurde bekommt das die BindingSource nicht mit. Das müßtest du dann per BindingSource.ResetBindings nachholen bzw. würde ich grundsätzlich das Binding erst vornehmen wenn ich auch Daten von meiner Datenschicht bekomme also nach der Set Methode und nicht im Constructor. Das sollte üblicherweise schon reichen. Ein Datenschicht(ich bezeichne deine Managerklasse mal so) die die Daten nochmal ändert nachdem sie die an irgendeinen Nutzer geliefert hat empfinde ich doch als eher unüblich.
Oder eben gleich besser zu einer intelligenteren Listen Klasse(wie z.B. BindingList) greifen.
Für diesen Beitrag haben gedankt: mats74
|
|
mats74
      
Beiträge: 189
Erhaltene Danke: 26
Win 10
VS 2017/19, C++, C#
|
Verfasst: Fr 13.01.12 15:35
Hallo zusammen
Ich habe den Code auch ausprobiert und der Tip mit der BindingList funktioniert einwandfrei.
Ich habe den Code folgendermassen angepasst:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53:
| private void button1_Click(object sender, EventArgs e) { Manager manager = new Manager(); manager.Set(); bindingSource1.DataSource = manager.Persons; foreach(Person person in manager.Persons) { comboBox1.Items.Add(person.Name.ToString()); } } class Manager { public BindingList<Person> Persons { get; set; } public Manager() { Persons = new BindingList<Person>(); } public void Set() { Persons.Add(new Person("Hans")); Persons.Add(new Person("Peter")); Persons.Add(new Person("Christina")); } } class Person : INotifyPropertyChanged { private string _name; public string Name { get { return _name; } set { _name = value; OnPropertyChanged(new PropertyChangedEventArgs("Name")); } } public event PropertyChangedEventHandler PropertyChanged; public Person(string name) { Name = name; } private void OnPropertyChanged(PropertyChangedEventArgs propertyChangedEventArgs) { PropertyChangedEventHandler propertyChanged = PropertyChanged; if (propertyChanged != null) propertyChanged(this, propertyChangedEventArgs); } } |
_________________ Gruss
mats74
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Fr 13.01.12 15:51
| Zitat: | | Ich habe den Code auch ausprobiert und der Tip mit der BindingList funktioniert einwandfrei. |
Bei dir hat das ganze nur nichts mit der BindingList zu tun  Da du im Click Event gar kein Databinding verwendest sondern in die Combobox kopierst.
Wenn sich jetzt im Hintergrund nochmal die Liste ändert(darum geht es scheinbar BlackMatrix) wird die Combobox das nicht automatisch mitbekommen. Bei Databinding mit BindingList schon.
|
|
mats74
      
Beiträge: 189
Erhaltene Danke: 26
Win 10
VS 2017/19, C++, C#
|
Verfasst: Fr 13.01.12 15:57
... Ups  voll ins Schwarze.
Naja, der olympische Gedanke zählt: Dabeisein ist alles  .
_________________ Gruss
mats74
|
|
BlackMatrix 
      
Beiträge: 243
Erhaltene Danke: 1
|
Verfasst: Fr 13.01.12 16:32
Ralf Jansen hat folgendes geschrieben : | | Zitat: | | Ich habe den Code auch ausprobiert und der Tip mit der BindingList funktioniert einwandfrei. | Wenn sich jetzt im Hintergrund nochmal die Liste ändert(darum geht es scheinbar BlackMatrix) wird die Combobox das nicht automatisch mitbekommen. Bei Databinding mit BindingList schon. |
Genau
Eigentlich wollte ich meine Klasse Manager, also meine Datenschicht, als gegeben ansehen. Daher will ich eigentlich auch keine BindingList anstatt einer List implementieren. Der Nächste verwendet meine Klasse und möchte gar nicht, dass die Personen an irgendein Element im UI gebunden sind und trotzdem ist die Liste eine BindingList.
Nun hatte ich mir von so einer Bindung erhofft, dass ich sie einmal im Konstruktor definiere und egal welchen Button ich in meiner Form klicke, meine Combobox immer genau die Personen widerspiegelt, die sich in der Liste befinden. Jeder Button ruft eine Methode meines Managerobjekts auf und bei jeder Methode kann es passieren, dass die List<Person> sich ändert. Wie realisiert man denn sowas?
Klar, ich könnte jetzt alle Clickereignisse der Buttons auf eine Ereignisbehandlungsroutine legen, aber irgendwie widerstrebt mir das, weil ich ja im Grunde genommen nur jeweils die Werte in der Liste angezeigt bekommen möchte, also nur einen UI Verweis von Daten an mein UI. Und dieser Verweis stellt meiner Meinung nach die Datenbindung dar, wo ich nicht jedes Mal sagen muss, jetzt aktualisiere das UI, weil es sein könnte, dass sich die Daten geändert haben.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Fr 13.01.12 16:50
| Zitat: | | bei jeder Methode kann es passieren, dass die List<Person> sich ändert. Wie realisiert man denn sowas? |
In dem man einen Listentyp benutzt der Bescheid sagt wenn sie sich ändert. Das tut List<T> nicht ist also eine Sackgasse. Wenn dich der Name BindingList stört(nur weil die so heißt muß man die ja nicht zum binden verwenden und wenn du die aus deiner Manager Klasse nur als IList<T> oder ähnliches veröffentlichst wird ja auch keiner drauf gestoßen das das eine entsprechende Liste ist und füllt sich genötigt zum binden) implementier halt eine eigene. Entscheidend ist IBindingList zu implementieren. Damit bekommst du ein ListChanged Event den du aus den Listen ändernden Methoden deiner Listenimplementierung() feuern mußt. Ich würde von Collection<T> ableiten und dort InsertItem, RemoveItem, SetItem überschreiben und denn ListChanged Event von dort feuern. Das sollte denke ich schon einen Großteil abdecken denn du brauchst.
|
|