Benutzer mit den meisten Antworten
welches Interface

Frage
-
Hallo,
ich habe eine Bindinglist vom Typ XX. Dieser Type hat zwei Propertys.
In Abhängigkeit dieser beiden Propertys soll beim anzeigen der Liste für jede Zeile etwas errechnetes angezeigt werden, also in Abhängigkeit dieser beiden Propertys.
Nun kann eines der beiden Propertys immer mal Nothing sein.
Wie kann ich gewährleisten, das die Anzeige nur dann erfolgt wenn alle beiden Propertys an die anzeigende Komponente gebunden wurden bzw. welches Interface muss in den Typ XX implementiert werden. und auf welches Ereignis muss die anzeigende Komponente reagieren. Im Typ selber kann ich ja sicher kein Ereignis auslösen?
Kommt damit jemand klar?
;-)
- Typ geändert Robert BreitenhoferModerator Donnerstag, 15. März 2012 14:46 Frage
Antworten
-
Hallo,
ich würde hier einfach ein eigenes Event erstellen, welches ausgelöst wird, wenn alle Properties gesetzt wurden. Wobei Du Dir hier halt genau überlegen willst, wann das Event ausgelöst werden soll. (Also z.B. nur einmalig sobald alle Properties das erste mal gesetzt wurden oder jedes mal, wenn eine Property verändert wurde und alle Properties einen Wert haben?
Aber dies ist ja beliebig codiebar - so wie Du es eben genau brauchst.
Mit den besten Grüßen,
Konrad
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 3. April 2012 13:26
-
Hallo,
Du kannst dazu System.ComponentModel.ISupportInitialize und System.ComponentModel.ISupportInitializeNotification verwenden.
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 3. April 2012 13:25
-
Hallo,
> Das hatte ich schon probiert.
Nun ja. Richtig gemacht, funktioniert es schon. Es ist aber kein sicherlich kein triviales Unterfangen, da weitere Datenbindung-Schnittstellen wie z.B. ICancelAddNew oder (in einem anderen, enger gekoppelteren Szenario) IEditableObject ebenfalls implementiert werden müßten (lies dazu Brian Noyes - Databinding with Windows Forms).
Aber sehen wir uns das Ganze aus der Vogelperspektive an. Vielleicht ergibt sich doch eine einfachere Möglichkeit. Was haben wir? - Wir haben eine BindingList<T>, wir haben ein Objekt von Typ T, das zwei Properties aufweist, die beide vorhanden sein müssen damit das Objekt angezeigt wird. Nur wenn beide Properties auf nicht-null-Werte gesetzt sind, soll das Objekt überhaupt in die Liste aufgenommen werden. Soweit so gut. Da lt. Prinzipien der objektorientierten Programmierung allein das T-Objekt über seinen Zustand Bescheid wissen sollte (also Person), kann das Hinzufügen einer Person zur Liste nicht außerhalb des Objekts erfolgen. Mit diesem Wissen im Hintergrund können wir dem T-Objekt zwei neue Methoden verpassen: AttachTo(ICollection<T>) und RemoveFrom(ICollection<T>). Was jetzt noch fehlt, ist ein Weg für die BindingList<T> diese Methoden aufzurufen und die ICollection.Add/Remove-Methoden zu verbergen. Dazu kann man ganz einfach eine PersonList-Klasse von BindingList<Person> ableiten und die zwei von Collection<T> geerbten Methoden Add() und Remove() neu einführen. In den Methoden können wir dann einfach person.AttachTo(this) bzw. person.DetachFrom(this) aufrufen. Die hinzuzufügende Person-Instanz kennt ihren internen Zustand und kann so am besten entscheiden, ob sie sich an die Liste anhängen kann oder nicht. Diese Entscheidung kann über das Strategy-Pattern weiter flexibilisiert werden, aber das ist ein anderes Thema. Wichtig ist, dass Person nun einen Verweis auf ein ICollection-Objekt hat und sich selbst der Liste hinzufügen oder - bei Bedarf - aus der Liste entfernen kann.Und - last but not least - natürlich könnte man auch BindingSource.Filter verwenden, um Ähnliches zu erreichen. Aber auch das führt m.E. in eine etwas andere Richtung.
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 3. April 2012 13:26
Alle Antworten
-
Hallo,
kannst Du uns näheres sagen, was Du überhaupt versuchst? Was willst Du wie anzeigen? Ein Interface brauchst Du ggf. garnicht. Aber ich werde erst einmal aus Deiner Schilderung nicht schlau.
Was willst Du wie und wo anzeigen? Welche Technology verwendest Du?
Du kannst der Komponente z.B. ein individuelles ToString() geben und dann halt das ToString() anzeigen. Das ist schon im Object drin und erfordert daher kein Interface.
Mit den besten Grüßen,
Konrad
-
Hallo U.,
Dein Typ sollte INotifyPropertyChanged implementieren. Für den berechneten Wert, könntest Du eine read-only Property verwenden. Bei jeder Änderung, (sprich in jedem Setter) sollte dann OnPropertyChanged() aufgerufen werden, um die an die Klasse bindenden Komponenten über diese Änderung zu benachrichtigen. Das könnte z.B. so aussehen:
public class Person : INotifyPropertyChanged { private string firstName; public string FirstName { get { return this.firstName; } private set { firstName = value; OnPropertyChanged("FirstName"); OnPropertyChanged("FullName"); } } private string lastName; public string LastName { get { return this.lastName; } private set { this.lastName = value; OnPropertyChanged("LastName"); OnPropertyChanged("FullName"); } } // Berechnete Property public string FullName { get { return String.IsNullOrEmpty(this.firstName) || String.IsNullOrEmpty(this.lastName) ? String.Empty : String.Format("{0} {1}", this.firstName, this.lastName); } } public Person(string firstName, string lastName) { FirstName = firstName; LastName = lastName; } #region INotifyPropertyChanged Member public event PropertyChangedEventHandler PropertyChanged; public virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName); if (handler != null) handler(null/*this*/, ea); } #endregion public override string ToString() { return FullName; } }
Wenn Du den dargestellten, berechneten Wert nicht aufgrund von Klassen-Properties, sondern ausgehend von der Instanz als solche erzeugen möchtest, kannst Du wie oben die Methode ToString() überschreiben.
INotifyPropertyChanged-Schnittstelle:
http://msdn.microsoft.com/de-de/library/system.componentmodel.inotifypropertychanged.aspxGewusst wie: Implementieren der INotifyPropertyChanged-Schnittstelle
http://msdn.microsoft.com/de-de/library/ms229614(v=vs.110).aspx
Edit: Kleines Refactoring von ToString(), welche nun nicht mehr null, sondern String.Empty zurückgibt (es ist durchaus erlaubt aus ToString() null zurückzugeben. Denkt man aber an die Consumer der obigen Klasse, ist es besser, wenn man einen leeren String zurückgibt, statt null. So werden unnötige NullReferenceExceptions vermieden).
Gruß
Marcel- Bearbeitet Marcel RomaModerator Donnerstag, 15. März 2012 14:42
-
> eine read-only Property verwenden
So ähnlich habe ich das gemacht.
Es würde mich aber doch interessieren ob es möglich ist die Klasse Person so um zu bauen, das eine Komponente(eine Eigene) erst reagiert, wenn alle Propertys von Person initialisiert sind.
Danke Ciao
-
Hallo,
ich würde hier einfach ein eigenes Event erstellen, welches ausgelöst wird, wenn alle Properties gesetzt wurden. Wobei Du Dir hier halt genau überlegen willst, wann das Event ausgelöst werden soll. (Also z.B. nur einmalig sobald alle Properties das erste mal gesetzt wurden oder jedes mal, wenn eine Property verändert wurde und alle Properties einen Wert haben?
Aber dies ist ja beliebig codiebar - so wie Du es eben genau brauchst.
Mit den besten Grüßen,
Konrad
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 3. April 2012 13:26
-
Hallo,
Du kannst dazu System.ComponentModel.ISupportInitialize und System.ComponentModel.ISupportInitializeNotification verwenden.
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 3. April 2012 13:25
-
Du kannst dazu System.ComponentModel.ISupportInitialize und System.ComponentModel.ISupportInitializeNotification verwenden.
Das hatte ich schon probiert. Ich bin mir aber nicht sicher ob dieses bei einzelnen gebundenen Datensätzen(quasi) funktioniert (oder ich habe dabei einen Fehler gemacht)
MfG
-
ich würde hier einfach ein eigenes Event erstellen,
Nunja, das könnte man, aber ich möchte hier Standard-Lösungen verwenden und hier geht es um Objekte einer Liste, also quasi einer Tabelle, die an eine Art eigenes Datagrid mit Datasource gebunden werden.
Vermutlich gibts dafür standardisierte Lösungen, die ich nur verstehen muss ...
Ciao
-
Hallo,
> Das hatte ich schon probiert.
Nun ja. Richtig gemacht, funktioniert es schon. Es ist aber kein sicherlich kein triviales Unterfangen, da weitere Datenbindung-Schnittstellen wie z.B. ICancelAddNew oder (in einem anderen, enger gekoppelteren Szenario) IEditableObject ebenfalls implementiert werden müßten (lies dazu Brian Noyes - Databinding with Windows Forms).
Aber sehen wir uns das Ganze aus der Vogelperspektive an. Vielleicht ergibt sich doch eine einfachere Möglichkeit. Was haben wir? - Wir haben eine BindingList<T>, wir haben ein Objekt von Typ T, das zwei Properties aufweist, die beide vorhanden sein müssen damit das Objekt angezeigt wird. Nur wenn beide Properties auf nicht-null-Werte gesetzt sind, soll das Objekt überhaupt in die Liste aufgenommen werden. Soweit so gut. Da lt. Prinzipien der objektorientierten Programmierung allein das T-Objekt über seinen Zustand Bescheid wissen sollte (also Person), kann das Hinzufügen einer Person zur Liste nicht außerhalb des Objekts erfolgen. Mit diesem Wissen im Hintergrund können wir dem T-Objekt zwei neue Methoden verpassen: AttachTo(ICollection<T>) und RemoveFrom(ICollection<T>). Was jetzt noch fehlt, ist ein Weg für die BindingList<T> diese Methoden aufzurufen und die ICollection.Add/Remove-Methoden zu verbergen. Dazu kann man ganz einfach eine PersonList-Klasse von BindingList<Person> ableiten und die zwei von Collection<T> geerbten Methoden Add() und Remove() neu einführen. In den Methoden können wir dann einfach person.AttachTo(this) bzw. person.DetachFrom(this) aufrufen. Die hinzuzufügende Person-Instanz kennt ihren internen Zustand und kann so am besten entscheiden, ob sie sich an die Liste anhängen kann oder nicht. Diese Entscheidung kann über das Strategy-Pattern weiter flexibilisiert werden, aber das ist ein anderes Thema. Wichtig ist, dass Person nun einen Verweis auf ein ICollection-Objekt hat und sich selbst der Liste hinzufügen oder - bei Bedarf - aus der Liste entfernen kann.Und - last but not least - natürlich könnte man auch BindingSource.Filter verwenden, um Ähnliches zu erreichen. Aber auch das führt m.E. in eine etwas andere Richtung.
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 3. April 2012 13:26
-
> Nur wenn beide Properties auf nicht-null-Werte gesetzt sind, soll das Objekt überhaupt in die Liste aufgenommen werden.
Das Problem ist leider, das beide Object beliebig null sein können, weswegen ich nix abprüfe n kann und wirklich warten muss bis die Initialisierung abgeschlossen ist.
trotzdem Danke erstmal
-
Das Problem ist leider, das beide Object beliebig null sein können, weswegen ich nix abprüfe n kann und wirklich warten muss bis die Initialisierung abgeschlossen ist. Trotzdem Danke erstmal.
Gerne.
Um sicherzugehen, dass Du verstanden hast, was ich meinte: Warten auf Initialisierung des Objekts ist nur dann nötig, wenn nicht das Objekt selbst entscheidet, ob es sich zur Liste hinzufügen möchte.
Wenn sich das Objekt aber selbst zur Liste hinzufügen kann, wird es ja noch seinen eigenen Zustand zu einem gegebenen Zeitpunkt überprüfen können, oder nicht? Über die Setter, "kennt" das Objekt immer den Zustand beider Properties und sobald beide gesetzt sind, kann es sich zur Liste hinzufügen und INotifyPropertyChanged.PropertyChanged auslösen damit die Liste sich selbst aktualisieren kann. Edit: Und wenn die zwei Properties nicht mehr gesetzt sind, kann sich das Objekt selbstverständlich auch wieder aus der Liste entfernen.Gruß
Marcel- Bearbeitet Marcel RomaModerator Montag, 26. März 2012 12:13
-
wenn nicht das Objekt selbst entscheidet, ob es sich zur Liste hinzufügen möchte.
Hi,
die Liste steht schon und muss auch ausgewertet werden, mit allen Objekten, auch wenn ein paar Properties null sind. Die Properties werden beim anzeigen zueinander verglichen, auch wenn eins null ist bzw. beide.
-
Hi,
Ja, dann hab ich wohl deine Anforderung: "Wie kann ich gewährleisten, das die Anzeige nur dann erfolgt wenn alle beiden Propertys an die anzeigende Komponente gebunden wurden" falsch interpretiert. In einem anderen Posting hattest Du auch angefordert: "Es würde mich aber doch interessieren ob es möglich ist die Klasse Person so um zu bauen, das eine Komponente (eine eigene) erst reagiert, wenn alle Propertys von Person initialisiert sind."
Was verstehst Du unter "die Anzeige" und "reagiert"?
Was genau soll und was soll nicht angezeigt werden?Gruß
Marcel- Bearbeitet Marcel RomaModerator Montag, 26. März 2012 13:25
-
erst reagiert, wenn alle Propertys von Person initialisiert sind."
Was verstehst Du unter "die Anzeige" und "reagiert"?
Was genau soll und was soll nicht angezeigt werden?Eien List soll angezeigt werden und eine andere Komponente soll die anzeigen, an diese Komponente werden die Datensätze/Klasse der Liste gebunden
Mit ISupportInitialize in der Komponente scheint es zu funktionieren - ich teste noch.
Ciao
-
Wenn Du mit Komponenten hantierst, deren Initialisierung relativ zueinander erfolgen soll, *muss* ISupportInitialize funktionieren: Dazu ist ja die Schnittstelle gedacht!
Solltest Du dennoch Probleme haben, poste bitte den Code oder lade ihn z.B. auf SkyDrive hoch und ich werde ihn mir ansehen. Ansonsten - wie schon gesagt - Brian Noyes erklärt diese Schnittstelle wunderbar in Databinding with Windows Forms, auch den Zusammenspiel mit weiteren Schnittstellen, die Du vielleicht noch einbauen mußt.Gruß
Marcel -
Hallo umocomp1,
Ich gehe davon aus, dass die Antworten Dir weitergeholfen haben.
Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.Grüße,
RobertRobert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.