Wie lassen Sie eine übergeordnete Klasse wissen über eine änderung der Kinder?
Dies ist ein Beispiel-code:
public class MyParent : INotifyPropertyChanged
{
List<MyChild> MyChildren;
public bool IsChanged
{
get
{
foreach (var child in MyChildren)
{
if (child.IsChanged) return true;
}
return false;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaiseChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
public class MyChild : INotifyPropertyChanged
{
private int _Value;
public int Value
{
get
{
return _Value;
}
set
{
if (_Value == value)
return;
_Value = value;
RaiseChanged("Value");
RaiseChanged("IsChanged");
}
}
private int _DefaultValue;
public int DefaultValue
{
get
{
return _DefaultValue;
}
set
{
if (_DefaultValue == value)
return;
_DefaultValue = value;
RaiseChanged("DefaultValue");
RaiseChanged("IsChanged");
}
}
public bool IsChanged
{
get
{
return (Value != DefaultValue);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaiseChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
Sagen wir mal ich habe jetzt zwei Instanzen meiner Klassen, einem als myParent, und die andere als myChild.
Ich habe zwei visuellen Elementen, die jeweils eine Eigenschaft, die gebunden an die IsChnaged Eigentum meines Instanzen; ElementA gebunden myParent.IsChanged und ElementB gebunden myChild.IsChanged.
Wenn myChild.Wert unterscheidet sich von seinem Standardwert, der myChild.IsChanged auf true gesetzt ist und die ElementB wird entsprechend aktualisiert.
Was ich brauche, ist, wenn entweder der myParent Kinder (die hier ist nur einer) haben Ihre IsChanged Wert auf true gesetzt, seine eigene (die Eltern) IsChanged Wert auf true gesetzt werden und der entsprechende
element (ElementA hier) werden entsprechend aktualisiert.
Den myParent.IsChanged nur einmal gelesen werden (wenn die Bindung eingestellt ist) und es hat keinen Sinn über seine Kinder ändern. Wo sollte ich die RaiseChanged("IsChanged") für MyParent? Wie kann ich lassen Sie die Eltern wissen, wenn Ihre Kinder sich verändert haben?
Vielen Dank im Voraus
- Sie konnte Ihr Kind Konstruktor nehmen als parameter das Eltern-Objekt, und während der Erstellung diese untergeordneten Objekte Sie können die parent-Objekt im Konstruktor.
- Das ist etwas, was ich gerne vermeiden, würde ich mir eher nicht vorstellen, dass ein Elternteil das Kind, entweder im Konstruktor oder sogar als Eigentum. Gibt es irgendeine andere Weise herum?
Du musst angemeldet sein, um einen Kommentar abzugeben.
INotifyPropertyChanged
bereits den Mechanismus für Sie: diePropertyChanged
Veranstaltung. Nur haben die Eltern einen Ereignishandler hinzuzufügen, um seine KinderPropertyChanged
, und dann in diesem handler aufrufenRaiseChanged("IsChanged");
Vielleicht möchten Sie auch um die
INotifyPropertyChanged
Implementierung in einer Basisklasse, und die haben Ihre (scheinbar) ViewModels Erben von diesem. Für diese option nicht benötigt, natürlich, aber es macht den code ein wenig sauberer.Update: In das parent-Objekt:
Du nicht wirklich etwas hinzufügen, um die Kind-Klasse, da hier bereits die Anhebung der richtige event, wenn Sie sich ändert.
PropertyChangeEventHandler
in diesem Fall.Tun diese Art der Kommunikation kann schwierig sein, vor allem, wenn Sie wollen, um Speicherverluste zu vermeiden, aufgrund der event-Handler, die Sie hook up. Es gibt auch den Fall der Umgang mit Elementen, die Hinzugefügt /entfernt aus der Sammlung.
Ich habe es wirklich genossen die Leistung und die Einfachheit der Continuous LINQ-Projekts auf codeplex. Es hat einige sehr umfangreiche Funktionen für die Einrichtung "Reaktive Objekte", "Kontinuierliche Werte" und "Kontinuierliche Sammlungen". Diese können Sie definieren Sie Ihre Kriterien als Linq-Ausdruck und lassen Sie dann die CLINQ Bibliothek halten Sie die zugrunde liegenden Werte up-to-date in Echtzeit.
In Ihrem Fall, konnten Sie die Eltern mit ein ContinuousFirstOrDefault() linq-Abfrage, sah für jedes Kind, wo "IsChanged == true". Sobald ein Kind setzt den Wert auf true und löst PropertyChanged, der kontinuierliche Wert erkennt die änderung und erheben eine entsprechende PropertyChanged-in die Muttergesellschaft.
Vorteile:
Hier ist, was der code Aussehen könnte:
Der obige code setzt die ContinuousFirstOrDefault in den Konstruktor so, dass es immer der überwachung. In einigen Fällen jedoch können Sie diese optimieren, indem Sie träge die Instanziierung der ContinuousFirstOrDefault nur, wenn der getter für "IsChanged" genannt wird. So dass Sie nicht starten Sie die überwachung für änderungen, bis Sie wissen, dass einige andere Stück code tatsächlich interessiert.
Können Sie vereinfachen Dinge für sich selbst, indem Sie Ihre Kinder in eine
ItemObservableCollection<T>
, wie besprochen, in diese Antwort. Das würde Ihnen erlauben, dies zu tun:Etwas, das ich nicht sehen in deinem code-Beispiel liefern, ist eigentlich ein Verweis von den Eltern auf das Kind. Es ist nicht genug, um einfach-Schnittstelle für die Kommunikation durch, aber man muss auch die Referenz. So etwas wie
myChild.parent = this;
gefolgt von der Bindung der event-Handler über den Kanal, in die "parent" - Eigenschaft des child-Objekts würde das so Aussehen:Habe ich nicht genug Kontext, um perfekt dieser code für Sie, aber dies sollte Sie bewegen sich in die richtige Richtung.
Ich bin nicht sehr vertraut mit C++ - code, aber das klingt viel wie der "observer-Muster" (Wikipedia, eine weitere gute Seite für OO-design. In einfachen Worten, jede Instanz sollte ein Ereignis auslösen, wenn Sie sich geändert hat, und jede andere Instanz und hält eine Referenz auf es fangen kann dieses Ereignis und angemessen reagieren.