• Blog
  • Bio

Eric Boumendil

Dependency Properties et Binding: création et utilisation

11 juin 2009 // archives .net c# wpf
Cet article est très ancien. Les choses ont bien changées depuis 2009. Le sujet abordé est conservé pour référence mais n'est certainement plus applicable en l'état.
Cet article est susceptible de référencer des images manquantes ou de contenir des erreurs de formatage sur son contenu. Il s'agit d'un import provenant d'un ancien blog.

Si vous ne savez pas du tout ce qu’est une Dependency Property, je vous invite à chercher sur MSDN. Rapidement, c’est un nouveau concept de propriété de classe dont :

  • la valeur est héritable par tous les objets enfants dans l’arbre des objets WPF.

  • on peut lier la valeur à la propriété d’un autre objet WPF.

Cet article va se focaliser sur l’aspect binding (liaison) à un objet Button, en C#. Un petit bout de XAML se trouve tout à la fin pour l’utilisation du Binding uniquement. Les propriétés attachées ne sont pas traitées.

Les conditions: Pour définir une liaison entre les propriétés de deux objets distincts (l’un sera la source, l’autre la cible), il faut que :

  • L’objet source dérive de la classe DependencyObject (qui implémente les méthodes SetValue et GetValue).

  • L’objet cible dérive de la classe FrameworkContentElement (qui implémente la méthode SetBinding).

A ma connaissance, tous les contrôles WPF héritent de FrameworkContentElement, la seconde condition ne posera donc jamais de réel doute. Par contre, si vous voulez lier une propriété d’une classe personnelle, il faut qu’elle dérive de DependencyObject (assembly WindowsBase, espace de nom System.Windows).

Créer sa propre Dependency Property :

Voici le code, pour créer une Dependency Property:

 1[...]
 2using System.Windows; // Ne pas oublier la référence à l'assembly WindowsBase (WPF Framework).
 3
 4public class MaClasse : DependencyObject
 5    {
 6        /// <summary>
 7        /// Lié à la propriété Text
 8        /// </summary>
 9        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MaClasse));
10
11        /// <summary>
12        /// Texte de ma classe
13        /// </summary>
14        public string Text
15        {
16            get
17            {
18                return (string)GetValue(TextProperty);
19            }
20            set
21            {
22                SetValue(TextProperty, value);
23            }
24        }
25    }

C’est tout ce qu’il faut pour créer une Dependency Property. Ce n’est donc pas beaucoup plus chargé que créer une propriété standard liée à un champ simple. Voici le code C# non WPF équivalent si, au lieu d’une propriété de dépendance, nous en avions une standard:

 1public class MaClasse
 2    {
 3        /// <summary>
 4        /// Lié à la propriété Text
 5        /// </summary>
 6        private string _text;
 7
 8        /// <summary>
 9        /// Texte de ma classe
10        /// </summary>
11        public string Text
12        {
13            get
14            {
15                return _text;
16            }
17            set
18            {
19                _text = value;
20            }
21        }
22    }

Revenons au premier code présenté: La ligne 2 importe l’espace de nom WindowsBase qui est obligatoire pour utiliser les objets de base de WPF.

La ligne 4 fait dériver notre objet de l’objet DepenencyObject, obligatoire pour contenir des propriétés de dépendance.

La ligne 9 fait deux choses :

  • Elle crée l’objet DependencyProperty (TextProperty). Notez qu’il s’agit d’un objet statique.

  • Elle inscrit cette propriété de dépendance grâce à la méthode Register(). Le premier paramètre est le nom de la propriété (utilisable dans du code XAML). Le second le type de valeur (si on essaie d’affecter une valeur d’un type incompatible, une exception sera levée). Le troisième le type de la classe qui encapsule cette propriété.

Cela pourrait suffire mais obligerait alors d’utiliser les méthodes SetValue() et GetValue() pour accéder à notre propriété. Pour l’encapsuler dans une propriété standard et retrouver un typage fort (la valeur d’une propriété de dépendance étant de type object), les lignes 14 à 24 créent la propriété Text dont le setter et le getter font appel aux deux méthodes citées ci-dessus. Ainsi, affecter la valeur de la propriété MaClass.Text affecte bien TextProperty.

Lier le contenu d’un contrôle à une Dependency Property :

Le code C# suivant est le contenu du fichier Window1.xaml.cs. Il s’agit d’une fenêtre WPF qui contient uniquement un Button nommé button1:

 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5using System.Windows;
 6using System.Windows.Controls;
 7using System.Windows.Data;
 8using System.Windows.Documents;
 9using System.Windows.Input;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12using System.Windows.Navigation;
13using System.Windows.Shapes;
14
15namespace WpfApplicationExample
16{
17    /// <summary>
18    /// Logique d'interaction pour Window1.xaml
19    /// </summary>
20    public partial class Window1 : Window
21    {
22        public Window1()
23        {
24            InitializeComponent();
25
26            MaClasse classeTest = new MaClasse();
27            Binding bind = new Binding();
28            bind.Source = classeTest;
29            bind.Path = new PropertyPath(MaClasse.TextProperty);
30            button1.SetBinding(Button.ContentProperty, bind);
31            classeTest.Text = "Nouveau texte";
32        }
33    }
34}

Vous voyez que l’important se trouve entre les lignes 26 à 31:

  • La ligne 26 instancie notre classe personnelle qui contient une Dependency Property.

  • La ligne 27 instancie une nouvelle liaison Binding.

  • La ligne 28 définit comme source de la liaison notre classe personnelle. C’est dans cette classe que la liaison récupérera la valeur liée.

  • La ligne 29 définit le chemin de la propriété de dépendance (il s’agit d’un champ statique).

  • Enfin, la ligne 30 met en place la liaison proprement dite: la propriété button1.Content (contenu du bouton) est liée à la propriété de dépendance MaClasse.TextProperty (qui est référencée par les propriétés bind.Source et bind.Path).

A chaque modification de la propriété classeTest.Text, le texte du bouton sera automatiquement rafraichi! Notez que si vous ne définissez pas au moins une fois la propriété de dépendance, sa valeur est null et le bouton n’affichera aucun contenu.

Ce nouveau concept est donc plutôt sympa à utiliser puisqu’il évite d’avoir à se soucier du rafraichissement du bouton. Ce qu’on fait généralement au travers d’un événement (mais pas nécessairement). Il faut bien avoir conscience que le mécanisme des Dependency Properties gère en interne un événement, mais l’implémentation est a priori robuste et fiable.

Et en XAML ?

XAML n’est pas l’objet de ce petit article mais voici l’utilisation de Binding entre deux contrôles WPF, un ScrollBar et un Button:

1<Grid>
2        <Grid.RowDefinitions>
3            <RowDefinition Height="20*"/>
4            <RowDefinition Height="80*"/>
5        </Grid.RowDefinitions>
6
7        <ScrollBar Grid.Row="1" Name="scroll" Value="50" Maximum="100" />
8        <Button Grid.Row="0" Height="23" Name="button1" VerticalAlignment="Top" Content="{Binding ElementName=scroll, Path=Value}"/>
9    </Grid>

Comme vous le voyez, c’est encore plus concis qu’en C# (bien qu’on ne fasse pas exactement la même chose): le binding est créé par l’attribut de la ligne 8: Content="{Binding ElementName=scroll, Path=Value}"

Lorsque vous déplacez le ScrollBar, sa valeur apparait dans le texte du bouton.

← 
Anciens articles du blog (2009-2014)
Apache2: Mise en place de plusieurs sites web sur un même serveur
 →
 
© 2026 Eric Boumendil
Haut de page