Dependency Property in Windows Presentation Foundation (con screencast)

Inizialmente si potrebbe approcciare questo argomento con scetticismo, dal momento che complica il panorama di tipi .NET conosciuti che tipicamente presentano campi semplici, proprietà, metodi ed eventi; ma si cambierà idea non appena capìti i problemi risolti attraverso le dependency property, che possono essere sfruttate per abilitare il data binding automatico, le animazioni, gli stili e molto altro. Diventa così possibile, per esempio, scrivere nel codice di markup (XAML) operazioni di layout (dipendenti per esempio dalla posizione del mouse) che altrimenti si dovrebbero gestire da codice procedurale (C# o VB.NET).

Una dependency property dipende da diversi provider per determinare il suo valore in ogni momento; l’obiettivo è di permettere funzionalità avanzate direttamente dall’interno del linguaggio di markup, senza bisogno di impostare le proprietà con codice procedurale.

 

Implementazione di una Dependency Property

Le dependency property sono normali proprietà di classi .NET che hanno una particolare struttura che le rende fruibili da WPF in modo speciale; nessun altro linguaggio .NET a parte XAML le riconosce come tali.

Per convenzione, tutti i campi DependencyProperty sono pubblici, statici e hanno il suffisso Property.

Poiché le dependency property sono campi statici, esse consumano una quantità di memoria di molto inferiore rispetto a che se fossero tipiche proprietà .NET di cui esiste in memoria una copia per istanza. Non a caso, 78 proprietà su 96 dei bottoni sono dependency property.

Una dependency property è implementata attraverso una chiamata al metodo statico DependencyProperty.Register che richiede un nome (es. IsMouseOver), un tipo (es. bool), il tipo della classe che le espone (es. Button) e, nella maggioranza dei casi, il nome della funzione di callback che viene chiamata quando tale proprietà cambia.

 

Change Notification

L’implementazione della callback nelle dependency property prende il nome di Change Notification; per rimanere nell’esempio precedente, la proprietà IsMouseOver permette di legare il suo valore (che dice quindi se il mouse si trova effettivamente sul controllo che la utilizza) ad un’altra proprietà del controllo stesso, come Background. Ciò significa che in questo caso non è necessario gestire il background del controllo andando a scrivere codice per l’event handler di MouseEnter e MouseLeave come vorrebbe il metodo classico, il quale fra l’altro “sporca” la business logic del file C# con codice di gestione del layout.

Grazie all’implementazione descritta nel punto precedente, è invece possibile legare il cambiamento di valore di IsMouseOver (da True a False o viceversa) al valore della proprietà Background del bottone.

Il video che segue mostra appunto come sfuttare le dependency property per impostare il colore di un bottone quando il mouse ci passa sopra. Normalmente potremmo implementare questo comportamento andando a definire e poi implementare, in codice procedurale C# o VB.NET, gli event handler per gli eventi di MouseEnter e MouseLeave. Grazie alle dependency property, invece, è possibile implementare questo comportamento solamente usando il codice di markup (XAML). Vediamo quindi come effettuare questa operazione, prima con il metodo classico e poi con le dependency property. Buona visione.