Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

.NET 3.0 : Comprendre les dependency properties et les propriétés attachées

Avec WPF, le databinding entre des objets métiers et l'interface utilisateur est devenu très facile. Par exemple, il est possible de lier une ListBox avec une collection d'objets métiers, et WPF se charge d'afficher comme il faut cette collection.

Il est même possible que WPF mettre automatiquement à jour l'interface à chaque modification de votre objet source. Pour cela, il y a deux possibilités. La première solution est que votre objet implémente INotifyPropertyChanged, et déclenche l'évènement PropertyChanged à chaque fois qu'une propriété est modifiée. WPF est alors obligé d'utiliser la réflexion.

Les dependency properties

La solution que nous allons aborder ici est d'utiliser des dependency objects. Cette classe est la base d'une très grande partie des classes WPF, et elle est aussi utilisée dans WF. Les dependency objects permettent d'utiliser des dependency properties.

Les dependency properties permettent aux objets d'avoir des propriétés dont la valeur peut dépendre de nombreuses choses. Par exemple, du data binding avec une autre propriété, ou d'une animation. En plus, elles fournissent un support pour l'auto validation et les valeurs par défaut. Les classes dérivées peuvent modifier le comportement d'une dependency property héritée très simplement.

Déclarer une DependencyProperty

Cela se fait très simplement. La première chose nécessaire est que votre objet (ici Planet) dérive de DependencyObject. La seconde (et dernière) chose nécessaire est de déclarer la propriété au moteur de la façon suivante :

public static readonly DependencyProperty MassProperty = DependencyProperty.Register("Mass", typeof(float), typeof(Planet));

Cette ligne fait plusieurs choses. D'abord, elle indique au moteur de DependencyObject de .NET 3.0 que chaque objet de type Planet (3e paramètre) aura une propriété (au sens DependencyProperty) de type float (2e paramètre).

"Mass" (le 1er paramètre) représente le nom de la propriété tel qu'il pourra être utilisé en XAML, il n'y a donc pas besoin d'utiliser la réflexion.

Quant à la variable MassProperty, il s'agit d'une "clé" qui permet de référencer cette propriété depuis le code, lorsqu'on souhaite effectuer une opération sur cette propriété. Il existe souvent des alternatives permettant d'utiliser le string "Mass" à la place, mais l'utilisation de la variable MassProperty est plus efficace.

Les conventions de nommage préconisent que la clé ait la signature suivante :

public static readonly DependencyProperty [NomDeLaPropriété]Property;

Déclarer une propriété CLR encapsulant cette DependencyProperty

Pour que cette propriété soit utilisable depuis le code de façon totalement invisible (sans que l'on ait à se préoccuper qu'il s'agisse d'une DependencyProperty ou d'une propriété CLR), on définit une propriété CLR (bien sur, ce n'est pas du tout obligatoire).

public float Mass
{
    get { return (float
)GetValue(MassProperty); }
    set { SetValue(MassProperty, value
); }
}

GetValue est une méthode de DependencyObject qui renvoie la valeur de la propriété (au sens DependencyProperty) dont la clé est indiquée en paramètre (ici, MassProperty). Cette méthode renvoie un objet de type object. Il faut donc le reconvertir en float avant de le renvoyer. SetValue fonctionne de la même façon. Notez que si vous passez à SetValue un objet de type différent que celui que vous avez déclaré par l'appel à DependencyProperty.Register, le Framework lèvera une exception.

Le fait de déclarer cette propriété CLR permet donc de repasser à un typage fort, puisque la vérification des types n'est faite qu'à l'exécution avec les DependencyProperty.

Les conventions de nommage préconisent la signature suivante pour cette propriété CLR :

public [TypeDeLaPropriété] [NomDeLaPropriété] { get; set;}

Les propriétés attachées

Une propriété attachée est une DependencyProperty qui est attachée à n'importe quel DependencyObject et pas seulement au type qui la définit.

En fait le système des DependencyProperty est conçu pour qu'une propriété d'une instance n'occupe pas de mémoire tant que cette propriété n'a pas été modifiée. En effet, le moteur de DependencyProperty revoie, de manière transparente, la valeur par défaut (qu'il est possible de préciser lors de l'appel à DependencyProperty.Register) si la propriété n'a jamais été modifiée.

Les propriétés attachées utilisent ce principe. En effet, si on prend l'exemple de la propriété Dock d'un contrôle, elle n'est lue que lorsque ce contrôle est placé à l'intérieur d'un DockPanel. Cela peut arriver à n'importe quel type de contrôle. Pourtant le nombre d'instances qui modifieront cette propriété est statistiquement très faible dans une application. Donc placer un attribut dock dans tous les contrôles (comme c'était le cas pour les WinForms) conduit à un gâchis de mémoire. Les DependencyProperty évitent ce gâchis.

De plus, sans les propriétés attachées, il n'est pas possible de rajouter de propriété à la classe Control, car nous n'en sommes pas l'auteur.

Déclarer une DependencyProperty attachée

La déclaration d'une propriété attachée se fait de façon très semblable à une DependencyProperty classique :

public static readonly DependencyProperty TopProperty = DependencyProperty.RegisterAttached("Top", typeof(double), typeof(Canvas));

Les arguments sont les même que pour une DependencyProperty classique : Nom de la propriété, type de la propriété, type qui déclare cette propriété.

Les conventions de nommage sont également les mêmes pour la déclaration de la clé :

public static readonly DependencyProperty [NomDeLaPropriété]Property;

Déclarer des accesseurs CLR encapsulant cette propriété attachée

Cette fois ci, il n'est pas possible d'utiliser une propriété CLR car il doit être possible de modifier la valeur de la propriété pour n'importe quel autre type (dérivant de DependencyProperty), et pas seulement pour celui qui définit la propriété (ici Canvas).

On utilise donc deux méthodes statiques :

public static double GetTop(DependencyObject target)
{
    return (double
)target.GetValue(TopProperty);
}

public static void SetTop(DependencyObject target, double
value)
{
    target.SetValue(TopProperty, value);
}

Les guidelines préconisent d'utiliser les signatures suivantes pour ces deux méthodes :

public static [TypeDeLaPropriété] Get[NomDeLaPropriété](DependencyObject target);
public static void Set[NomDeLaPropriété](DependencyObject target, [TypeDeLaPropriété] value);

Conclusion

Le Framework .NET 3.0 est basé sur les DependencyProperty. WPF et WF les utilisent abondamment (WCF ne les utilise pas à ma connaissance). Elles fournissent les fonctionnalités suivantes :

  • Ressources
  • Data binding
  • Styles
  • Animations
  • Metadatas
  • Héritage

L'inconvénient principal, c'est qu'elles obligent l'objet qui les utilise à hériter de DependencyObject.

Pour plus d'informations, je vous conseille d'aller voir les pages suivantes :

Publié lundi 19 février 2007 15:53 par RaptorXP
Classé sous : , , , , ,
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

# re: .NET 3.0 : Comprendre les dependency properties et les propriétés attachées

Hello,

Merci pour ce très bon article! Par contre, le débutant que je suis à dut aller se renseigner pour avoir la def d'une attached property...

Merci encore !

+++

mardi 7 avril 2009 10:45 by jmix90
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Conf’SharePoint : 10 bonnes raisons pour ne pas la rater par Le petit blog de Pierre / Pierre's little blog le 05-14-2013, 02:24

- [Event] Soirée de lancement Agile .NET France à Lyon par Blog Agile/ALM de Vincent THAVONEKHAM le 05-13-2013, 01:29

- .NET / Debug : inspection de la mémoire d'applications .NET (dump ou processus live) : première livraison d'une librairie .NET par Microsoft par CoqBlog le 05-11-2013, 22:21

- SharePoint : Incompatibilité avec Internet Explorer 10 (IE10) par Blog Technique de Romelard Fabrice le 05-08-2013, 16:29

- AutoSPInstaller pour SharePoint 2013 maintenant disponible en “RTM” par Julien Chable le 05-06-2013, 23:30

- [TFS2010] A la recherche du Shelveset perdu par Blog de Jérémy Jeanson le 05-03-2013, 21:46

- .NET / Debug post-mortem : obtenir le fichier mscordacwks.dll correspondant à un dump quand on n'a plus d'accès direct à ce fichier par CoqBlog le 04-28-2013, 19:57

- [W8] Afficher un graphe par CPU dans le gestionnaire des tâches par Blog de Jérémy Jeanson le 04-28-2013, 17:48

- [WCF] Limiter proprement l’accès à vos ressources serveur par Blog de Jérémy Jeanson le 04-26-2013, 22:59

- Event : Je serai speaker à la Conf’SharePoint par Blog Technique de Romelard Fabrice le 04-26-2013, 12:00