Donnerstag, 8. Mai 2008

AttachedProperties richtig initialisieren

Manchmal ist es angebracht, nachdem sich ein Objekt bei einem AttachedProperty registriert hat, einige Initialisierungen durchzuführen. Hierbei kann in der Set Methode, nach dem Setzen des AttachedProperty, z.B. eine Initialisierungsmethode aufgerufen werden.

public
static
void SetAttachedProperty(DependencyObject obj, int value)

{

obj.SetValue(AttachedProperty, value);

InitializeProperty();

}

Die Set-Methode macht nichts Weiteres, als bei dem übergebenen DependencyObjekt SetValue aufzurufen. Der eigentliche Wert der AttachedProperty wird also wie eine ganz normale DependencyProperty gesetzt. Stellen Sie sich einfach vor, eine DependencyProperty ist nichts anderes als ein Schlüssel der zusammen mit einem Wert in einem Dictionary gespeichert wird. Jedes DependencyObject hat so ein Dictionary. Die Werte können aber auch von anderen Objekten abgefragt und gesetzt werden.

Um eine AttachedProperty zu setzen, reicht es tatsächlich lediglich die DependencyProperty am eigenen Objekt zu setzen und nicht am Containerobjekt durch Set[Property]! Das bedeutet aber auch, dass die Initialisierungsmethode nicht mehr aufgerufen wird, da die AttachedProperty über einen anderen Weg gesetzt wird. Nun kann man es natürlich zur Konvention machen in dem in einem API vorschreibt, dass AttachedProperties immer über Set[Property] gesetzt werden müssen. So ist der XAMLReader drauf angewiesen, dass wenn er eine AttachedProperty im Markup erkennt, auch eine entsprechende Set-Methode verfügbar ist, die er aufrufen kann.

Trotzdem ist es besser eine Initialisierung anders durchzuführen. Wie? Über einen Callbackmechanismus. Jede DependencyProperty verfügt über Metadaten die es erlauben, Code bzw. Callbacks für Validierungen, Änderungen etc. zu hinterlegen. Ändert sich z.B. der Wert einer DependencyProperty, so wird der Callback aufgerufen und die Initialisierung kann durchgeführt werden. Dieser Mechanismus funktioniert unabhängig davon wie eine DependencyProperty, gesetzt wurde.

public
static
readonly
DependencyProperty PropertyWithCallback;


 

//Definition der Metadaten mit Callback

PropertyMetadata metadata = new
PropertyMetadata();

metadata.PropertyChangedCallback += OnPropertyWithCallbackChanged;


 

//Registrierung der DependencyProperty

PropertyWithCallback = DependencyProperty.RegisterAttached("PropertyWithCallback",


typeof(int), typeof(Window1), metadata);


 

//Der Callback ruft die eigentliche Initializierungsmethode auf

private
static
void OnPropertyWithCallbackChanged(DependencyObject obj, DependencyPropertyChangedEventArgs value)

{

InitializeProperty();

}

Keine Kommentare: