PropertyChanged-Benachrichtigung für berechnete Eigenschaften

8

Ich entwickle eine Anwendung in Silverlight2 und versuche, dem Model-View-ViewModel-Muster zu folgen. Ich verbinde die IsEnabled-Eigenschaft für einige Steuerelemente mit einer booleschen Eigenschaft im ViewModel.

Ich stoße auf Probleme, wenn diese Eigenschaften von anderen Eigenschaften abgeleitet sind. Angenommen, ich habe eine Schaltfläche "Speichern", die nur aktiviert werden soll, wenn es möglich ist, Daten zu speichern (Daten wurden geladen, und wir sind gerade nicht damit beschäftigt, Daten in der Datenbank zu speichern).

Ich habe also ein paar Eigenschaften wie folgt:

%Vor%

Was ich jetzt tun möchte, ist folgendes:

%Vor%

Beachten Sie jedoch das Fehlen der Benachrichtigung über geänderte Eigenschaften.

Die Frage ist also: Was ist eine saubere Möglichkeit, eine einzelne boolesche Eigenschaft zu offenbaren, an die ich binden kann, die aber berechnet wird, anstatt explizit festgelegt zu werden, und Benachrichtigungen bereitstellt, damit die Benutzeroberfläche korrekt aktualisiert werden kann?

BEARBEITEN: Danke für die Hilfe an alle - Ich habe es in die Wege geleitet und wollte ein benutzerdefiniertes Attribut erstellen. Ich poste hier die Quelle, falls jemand interessiert ist. Ich bin mir sicher, dass es auf eine sauberere Art und Weise getan werden könnte. Wenn Sie Fehler sehen, fügen Sie einen Kommentar oder eine Antwort hinzu.

Im Grunde habe ich eine Schnittstelle erstellt, die eine Liste von Schlüssel / Wert-Paaren definiert, um zu halten, welche Eigenschaften von anderen Eigenschaften abhängen:

%Vor%

Ich machte dann das Attribut, um auf jede Eigenschaft zu gehen:

%Vor%

Das Attribut selbst speichert nur eine einzelne Zeichenfolge. Sie können mehrere Abhängigkeiten pro Eigenschaft definieren. Die Eingeweide des Attributs befinden sich in der statischen Funktion BuildDependentPropertyList. Sie müssen dies im Konstruktor Ihrer Klasse aufrufen. (Wer weiß, ob es eine Möglichkeit gibt, dies über ein class / constructor-Attribut zu tun?) In meinem Fall ist das alles in einer Basisklasse versteckt, also fügen Sie in den Unterklassen die Attribute einfach in die Eigenschaften ein. Dann ändern Sie Ihr OnPropertyChanged-Äquivalent, um nach Abhängigkeiten zu suchen. Hier ist meine ViewModel-Basisklasse als Beispiel:

%Vor%

Abschließend legen Sie die Attribute für die betroffenen Eigenschaften fest. Ich mag diesen Weg, weil die abgeleitete Eigenschaft die Eigenschaften hält, von denen sie abhängt, und nicht umgekehrt.

%Vor%

Der große Nachteil hier ist, dass es nur funktioniert, wenn die anderen Eigenschaften Mitglieder der aktuellen Klasse sind. Wenn sich im obigen Beispiel this.Session.IsLocked ändert, wird die Benachrichtigung nicht übermittelt. Die Art und Weise, wie ich das umgehe, besteht darin, diese.Session.NotifyPropertyChanged zu abonnieren und PropertyChanged für "Session" zu setzen. (Ja, dies würde dazu führen, dass Ereignisse ausgelöst werden, wo sie nicht benötigt werden)

    
geofftnz 27.02.2009, 02:24
quelle

3 Antworten

6

Der traditionelle Weg, dies zu tun, ist, einen OnPropertyChanged-Aufruf zu jeder der Eigenschaften hinzuzufügen, die sich auf Ihre berechnete auswirken könnten, wie folgt:

%Vor%

Dies kann etwas unordentlich werden (wenn sich beispielsweise Ihre Berechnung in CanSave ändert).

Ein (sauberer? Ich weiß nicht) Weg, um dies zu umgehen, wäre, OnPropertyChanged zu überschreiben und den Aufruf dort zu machen:

%Vor%     
Matt Hamilton 27.02.2009, 02:33
quelle
2

Sie müssen eine Benachrichtigung für die Änderung der CanSave-Eigenschaft hinzufügen, wenn sich eine der davon abhängigen Eigenschaften ändert:

%Vor%

Und

%Vor%     
Franci Penov 27.02.2009 02:31
quelle
1

Wie wäre es mit dieser Lösung?

%Vor%

Rufen Sie dann UpdateCanSave () in den Setter von IsLoaded und DatabaseBusy auf?

Wenn Sie die Setter von IsLoaded und DatabaseBusy nicht ändern können, weil sie sich in verschiedenen Klassen befinden, könnten Sie versuchen, UpdateCanSave () in der PropertyChanged-Ereignisbehandlungsroutine für das Objekt aufzurufen, das IsLoaded und DatabaseBusy definiert.

    
KeithMahoney 27.02.2009 02:32
quelle