26.4 Validieren einer Abhängigkeitseigenschaft
Nun müssen wir noch auf einen ausgesprochen wichtigen Punkt zu sprechen kommen. Bei der Definition von CLR-Eigenschaften haben wir bisher immer die set- und get-Zweige dazu benutzt, Überprüfungen im Zusammenhang mit der Wertübergabe oder der Auswertung vorzunehmen oder möglicherweise Ereignisse auszulösen. Von diesem allgemeinen Prinzip sollten Sie beim Wrapper einer Abhängigkeitseigenschaft grundsätzlich immer Abstand nehmen. Stattdessen bieten sich uns mit den Delegaten ValidateValueCallback und CoerceValueCallback Alternativen an, die die Aufgabe der Validierung übernehmen.
26.4.1 Validieren mit »ValidateValueCallback«

Dieser Delegat kann den neuen Eigenschaftswert ganz allgemein entweder akzeptieren oder verwerfen, repräsentiert also einen Boolean. Er ersetzt die Überprüfung des Wertes, die bei herkömmlichen CLR-Eigenschaften normalerweise im set-Zweig erfolgt.
Der ValidateValueCallback-Delegat hat prinzipiell dieselbe Aufgabe wie der noch zu diskutierende CoerceValueCallback-Delegat. Bei der Validierung hat der ValidateValueCallback-Delegat jedoch keine Kenntnis vom Objekt selbst. Daher wird der Delegat immer dann eingesetzt, wenn eine Überprüfung allgemeingültig ist, also für jedes Objekt die gleichen Bedingungen angesetzt werden können. Objekteigenschaften können zur Validierung des neuen Wertes nicht herangezogen werden. Hinsichtlich unserer Klasse Circle wäre es zum Beispiel naheliegend, sicherzustellen, dass der Radius nicht kleiner 0 sein darf.
Die Bekanntgabe des ValidateValueCallback-Delegaten erfolgt als Argumentübergabe an die Register-Methode der Klasse DependencyProperty.
RadiusProperty = DependencyProperty.Register("Radius", typeof(int),
typeof(Circle), meta,
new ValidateValueCallback(IsRadiusValid));
Listing 26.12 Validieren einer Dependency Property
Die auf den Delegaten beruhende Rückrufmethode erwartet als einziges Argument den Wert, den es zu überprüfen gilt. Die Übergabe des zu prüfenden Wertes erfolgt an einen Parameter vom Typ Object und muss demnach innerhalb der validierenden Methode in den passenden Datentyp konvertiert werden. Der Rückgabewert ist true, wenn der Wert akzeptiert werden kann, ansonsten false.
private static bool IsRadiusValid(object value) {
if ((int)value >= 0) return true;
return false;
}
Listing 26.13 Die Definition der Rückrufmethode
Die Rückgabe von false löst eine Ausnahme aus, die behandelt werden muss.
26.4.2 Validieren mit »CoerceValueCallback«
Der Delegat CoerceValueCallback wird dazu benutzt, festzustellen, ob der bis zu diesem Zeitpunkt gebildete neue Eigenschaftswert im Kontext anderer Objekteigenschaften als gültig angesehen werden kann. Nehmen wir dazu das typische Beispiel eines ProgressBar-Steuerelements (Fortschrittsbalken). Mit den Werten Minimum und Maximum werden die Bereichsgrenzen abgesteckt, mit Value der aktuelle Wert. Überschreitet Value den von Maximum definierten Grenzwert, kann das nicht akzeptiert werden. Andererseits darf Value auch die Einstellung von Minimum nicht unterschreiten. Zur Vermeidung dieser Inkonsistenz eignet sich der CoerceValueCallback-Delegat.
Der Delegat beschreibt eine Methode mit zwei Parametern. Der erste liefert dabei die Referenz auf das Objekt, für das der Eigenschaftswert geprüft werden soll. Dabei muss es sich um ein Objekt vom Typ DependencyObject handeln. Der zweite Parameter ist der zu validierende Wert. Der Rückgabewert ist vom Typ Object und beschreibt den eventuell umgewandelten, akzeptablen Eigenschaftswert.
Ein CoerceValueCallback-Delegat wird über die gleichnamige Eigenschaft des PropertyMetadata-Objekts definiert (siehe auch Tabelle 26.1), beispielsweise folgendermaßen:
FrameworkPropertyMetadata meta = new FrameworkPropertyMetadata(...);
meta.CoerceValueCallback = new CoerceValueCallback(CoerceRadius);
Listing 26.14 Definition des »CoerceValueCallback«-Delegaten
Nehmen wir an, in der Klasse Circle wäre noch eine CLR-Eigenschaft Maximum definiert, die den maximalen Radius eines Circle-Objekts festschreiben soll. In diesem Fall dürfte der Wert des Radius den vorgegebenen Maximalwert nicht überschreiten. Da die Eigenschaft Maximum für jedes Objekt unterschiedlich sein kann, muss eine Validierung gegen den objektspezifischen Wert durchgeführt werden.
private static object CoerceRadius(DependencyObject d, object value) {
if (((Circle)d).Maximum >= (int)value)
return value;
return ((Circle)d).Maximum;
}
Listing 26.15 Prüfen gegen eine objektspezifische Eigenschaft
Es würde sich auch hinsichtlich der Eigenschaft Maximum anbieten, diese als Abhängigkeitseigenschaft zu implementieren. Um den Code überschaubar zu halten, wird die Eigenschaft als normale CLR-Property angegeben.
Den kompletten Code der Klasse Circle finden Sie auf der Buch-DVD unter ..\Beispiel\Kapitel 26\DependencyPropertySample.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.