La liaison de données est une composante fondamentale de WPF, permettant la mise en œuvre efficace du modèle MVVM. Elle établit une connexion dynamique entre deux propriétés, où la source entraîne automatiquement la mise à jour de la cible, ce qui diminue la dépendnace aux événements.
La source peut provenir de divers objets, tandis que la cible doit obligatoirement être une propriété de dépendance sur un objet de dépendance. Les scénarios de source incluent :
- Les objets de dépandance (DependencyObject), pour lier aux propriétés de dépendance.
- Les objets CLR, pour lier aux propriétés publiques, sous-propriétés et indexeurs via la réflexion CLR.
- Les objets dynamiques, implémentant IDynamicMetaObjectProvider.
- Les objets ADO.NET, comme DataTable, avec suport des notifications via IBindingList.
- Les objets XML, avec requêtes XPath sur XmlNode ou XmlDocument.
Un cas courant est la liaison entre éléments de l'interface. Par exemple, modifier la valeur d'un curseur met à jour dynamiquement la taille de police d'un champ de texte :
<StackPanel>
<TextBox FontSize="{Binding ElementName=controlSlider, Path=CurrentValue}" Text="Bienvenue dans WPF." Name="champTexte" />
<Slider Name="controlSlider" Maximum="30" Minimum="12" />
<TextBlock Text="{Binding ElementName=controlSlider, Path=CurrentValue}" Name="afficheur" />
</StackPanel>
En code C#, cela peut être configuré manuellement pour plus de flexibilité :
var liaison = new Binding
{
Source = this.controlSlider,
Path = new PropertyPath("CurrentValue")
};
BindingOperations.SetBinding(this.champTexte, TextBox.FontSizeProperty, liaison);
BindingOperations.SetBinding(this.afficheur, TextBlock.TextProperty, liaison);
La direction du flux de données est contrôlée par la propriété Mode, avec des options comme OneWay (source vers cible), TwoWay (bidirectionnel), OneTime (initial), OneWayToSource (cible vers source) et Default (basé sur le contrôle).
Le déclenchement de la liaison est géré via UpdateSourceTrigger, qui peut être LostFocus, PropertyChanged, Explicit ou Default, efficace principalement en mode TwoWay ou OneWayToSource. On peut aussi forcer la mise à jour :
var expression = BindingOperations.GetBindingExpression(this.champTexte, TextBox.FontSizeProperty);
expression.UpdateSource();
Pour lier à des objets CLR, il est essentiel d'implémenter l'interface INotifyPropertyChanged. Voici un exemple avec une classe Produit :
public class Produit : INotifyPropertyChanged
{
private decimal prixUnitaire;
public decimal PrixUnitaire
{
get { return prixUnitaire; }
set
{
if (prixUnitaire != value)
{
prixUnitaire = value;
OnPropertyChanged("PrixUnitaire");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Dans cet exemple, la modification de PrixUnitaire dans le code déclenche une notification, mettant à jour automatiquement l'interface liée. Pour les collections, on utilise ObservableCollection<T> qui fournit des notifications intégrées.
Des mécanismes additionnels comme les modèles de données, les convertisseurs de valeurs, les liaisons multiples et la validation enrichissent les scénarios de liaison.