Entwickler-Ecke

Sonstiges (.NET) - DataBindings


Määx - Di 12.03.13 15:04
Titel: DataBindings
Hallo zusammen,

ich habe mir eine Klasse geschireben, an deren Instanzen ich diverse GUI-Elemente binden möchte.
Dazu erbe ich von der Klasse INotifyPropertyChanged und "alarmiere" Änderungen wie folgt:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
  if (PropertyChanged != null)
  {
    PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
  }
}

Die einzelnen Variablen editiere ich dann wie folgt:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
[DataMember]
public string Person_Telefonnummer {
   get { return _Person_Telefonnummer; }
   set
   {
      if (_Person_Telefonnummer != value)
      {
         _Person_Telefonnummer = value;
         OnPropertyChanged("Person_Telefonnummer");
      }
   }
}
private string _Person_Telefonnummer;

Das funktioniert auch so weit sehr gut. Darüber hinaus habe ich aber auch ICollections als DataSource für ListBoxen ausgewählt. Die ICollections habe ich quasi identishc angelegt, erhalte hier jedoch bei dem Add-Befehl keine aktualisierung der ListBox. Woran kann dies liegen?

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
[DataMember]
public ICollection<Fahrzeug> Fahrzeuge
{
  get { return _Fahrzeuge; }
  set
  {
     if (_Fahrzeuge != value)
     {
        _Fahrzeuge = value;
        OnPropertyChanged("Fahrzeuge");
     }
  }
}
private ICollection<Fahrzeug> _Fahrzeuge = new Collection<Fahrzeug>();


Kann mir jemand einen Tipp geben wieso dies mit ICollection incht funktioniert? Bzw. habe ich etwas mit dem DataBindings falsche gemacht?

Vielen Dank an alle!

Edit: achso, ich denke man muss anstelle OnPropertyChanged für die Collections ein Event der Kategorie NotifyCollectionChangedEventHandler aufrufen. Leider bekomme ich das bishe rnicht richtig hin!


Ralf Jansen - Di 12.03.13 15:17

<Pedant active="true">Du erbst nicht von INotifyPropertyChanged du implementierst INotifyPropertyChanged</Pedant>

Wenn Fahrzeuge über eine Datenbindung geändert werden wird dein Setter nie gefeuert. Denn die Collection ändert sich ja nicht (es wird nie eine neu Liste zugewiesen) sondern nur der Inhalt der Collection ändert sich. Den Typ den du beim Aufruf der Fahrzeug Property zurückgibst muss schon INotifyPropertyChanged beherschen.

Edit: Was macht das DataMember Attribut hier? Eine Klasse die zum Binden an eine UI ausgelegt ist und für einen Contract gedacht ist verbindet gefühlt 2 Dinge die nicht zusammengehören.


Th69 - Di 12.03.13 15:30

Hallo Määx,

anstatt Collection<T> solltest du mal eine ObservableCollection<T> verwenden, da diese von sich aus schon INotifyCollectionChanged unterstützt.


Ralf Jansen - Di 12.03.13 15:36

Oder BindingList<T> je nachdem was du genau willst. BindingList reicht auch PropertyChanged Events der enthalten Objekte als ListChanged Event weiter. ObservableCollection wirft nur Events beim hinzufügen/löschen von Klassen zur Collection.


Määx - Di 12.03.13 15:44

Zitat:
Denn die Collection ändert sich ja nicht (es wird nie eine neu Liste zugewiesen) sondern nur der Inhalt der Collection ändert sich

ah ok, das ist logisch! Dann werde ich mir mal die BindingLists anschauen. Denke das wird das sein, was ich benötige.

Zitat:
Was macht das DataMember Attribut hier? Eine Klasse die zum Binden an eine UI ausgelegt ist und für einen Contract gedacht ist verbindet gefühlt 2 Dinge die nicht zusammengehören.

Ich lese im Server die daten aus einer DB und erzeuge dann ein neues Objekt mit den obigen Elementen um sie an den Client zu senden - daher DataMember. Im Client stelle ich einige dieser Elemente u.a. direkt in der GUI dar. Damit ich im Client nicht das erhaltene Objekt manipulieren muss und somit ja wieder "Zeit verliere", habe ich hier direkt die Bindung mit aufgenommen.

Hat das irgendwelche Nachteile die ich bis jetzt noch nicht bemerkt habe?


Ralf Jansen - Di 12.03.13 15:51

Wie hast du den den Transport vom Server zum Client bewerkstelligt? In den üblichen Verfahren die ich mir vorstelle hat man auf dem Client nicht mehr die konkrete Klasse die auf dem Server den DataContract darstellt sondern nur noch eine Proxy Klasse die der Oberfläche des DataContracts entspricht. Jede interne Logik wie z.B. die Implementierung von INotifyProprtyChanged wäre dann weg oder hätte zumindest nichts mit dem zu tun was du in der Contract Klasse bewerkstelligst hast. Eine Ausnahme wäre zum Beispiel wenn man explizit die Klasse in beiden Prozessen benutzt und explizit den NetDataContractSerializer verwendet hätte.


Määx - Di 12.03.13 16:00

Ich habe eine WCF-Dienstanwendung erstellt in der ich den Datenvertrag festlege. Wenn ich nun im Client eine ServiceReference hinzufüge und mein Objekt Person abrufe, gibt mir VisualStudio bereits den Server-Datentyp vor. Entsprechend arbeite ich im Client auf der gleichen Klasse wie im Server. Wenn ich das ganze jetzt aber unabhängiger gestalten kann und das auch eher die Form ist, wie man es machen sollte, würde ich den zusätzlichen Rechenaufwand aber auch in kauf nehmen. Aber wie müsste ich dann den Server-Call machen? Wie gesagt, mir wird das Server-Objekt ja von VS schon vorgegeben?
Vielen Dank