Propriétés de chargement et de dépendance XAML (WPF .NET)

L’implémentation de Windows Presentation Foundation (WPF) de son processeur XAML (Extensible Application Markup Language) est intrinsèquement consciente de la propriété de dépendance. Par conséquent, le processeur XAML utilise des méthodes de système de propriétés WPF pour charger des attributs de propriété de dépendance XAML et traiter entièrement des wrappers de propriété de dépendance à l’aide de méthodes de système de propriétés WPF comme GetValue et SetValue. Par conséquent, si vous ajoutez une logique personnalisée au wrapper de propriété de votre propriété de dépendance personnalisée, elle ne sera pas appelée par le processeur XAML lorsqu’une valeur de propriété est définie en XAML.

Prérequis

L’article suppose une connaissance de base des propriétés de dépendance et que vous avez lu la vue d’ensemble des propriétés de dépendance. Pour suivre les exemples de cet article, il vous aide à connaître le langage XAML (Extensible Application Markup Language) et à savoir comment écrire des applications WPF.

Performances du chargeur XAML WPF

Il est moins coûteux de calcul pour le processeur XAML WPF d’appeler SetValue directement pour définir la valeur d’une propriété de dépendance, plutôt que d’utiliser le wrapper de propriété d’une propriété de dépendance.

Si le processeur XAML a utilisé le wrapper de propriétés, il faudrait déduire l’intégralité du modèle objet du code de stockage uniquement en fonction des relations de type et de membre indiquées dans le balisage. Bien que le type puisse être identifié à partir du balisage à l’aide d’une combinaison d’attributs et d’attributs xmlns d’assembly, l’identification des membres, la détermination des membres pouvant être définis en tant qu’attribut et la résolution des types de valeurs de propriété pris en charge, nécessite une réflexion approfondie à l’aide PropertyInfode .

Le système de propriétés WPF gère une table de stockage des propriétés de dépendance implémentée sur un type dérivé donné DependencyObject . Le processeur XAML utilise cette table pour déduire l’identificateur de propriété de dépendance d’une propriété de dépendance. Par exemple, par convention, l’identificateur de propriété de dépendance pour une propriété de dépendance nommée ABC est ABCProperty. Le processeur XAML peut définir efficacement la valeur de n’importe quelle propriété de dépendance en appelant la SetValue méthode sur son type conteneur à l’aide de l’identificateur de propriété de dépendance.

Pour plus d’informations sur les wrappers de propriétés de dépendance, consultez Propriétés de dépendance personnalisées.

Implications pour les propriétés de dépendance personnalisées

Le processeur XAML WPF contourne les wrappers de propriétés et appelle SetValue directement pour définir une valeur de propriété de dépendance. Par conséquent, évitez de placer une logique supplémentaire dans l’accesseur set de votre propriété de dépendance personnalisée, car cette logique ne s’exécutera pas lorsqu’une valeur de propriété est définie en XAML. L’accesseur set ne doit contenir qu’un SetValue appel.

De même, les aspects du processeur XAML WPF qui obtiennent des valeurs de propriété contournent le wrapper de propriétés et appellent GetValuedirectement . Par conséquent, évitez également de placer une logique supplémentaire dans l’accesseur get de votre propriété de dépendance personnalisée, car cette logique ne s’exécutera pas lorsqu’une valeur de propriété est lue en XAML. L’accesseur get ne doit contenir qu’un GetValue appel.

Propriété de dépendance avec l’exemple wrapper

L’exemple suivant montre une définition de propriété de dépendance recommandée avec des wrappers de propriétés. L’identificateur de propriété de dépendance est stocké en tant que public static readonly champ et les get set accesseurs ne contiennent aucun code au-delà des méthodes de système de propriétés WPF nécessaires qui sauvegardent la valeur de propriété de dépendance. Si vous avez du code qui doit s’exécuter lorsque la valeur de votre propriété de dépendance change, envisagez de placer ce code dans la PropertyChangedCallback propriété de votre dépendance. Pour plus d’informations, consultez rappels modifiés par propriété.

// Register a dependency property with the specified property name,
// property type, owner type, and property metadata. Store the dependency
// property identifier as a public static readonly member of the class.
public static readonly DependencyProperty AquariumGraphicProperty =
    DependencyProperty.Register(
      name: "AquariumGraphic",
      propertyType: typeof(Uri),
      ownerType: typeof(Aquarium),
      typeMetadata: new FrameworkPropertyMetadata(
          defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"),
          flags: FrameworkPropertyMetadataOptions.AffectsRender,
          propertyChangedCallback: new PropertyChangedCallback(OnUriChanged))
    );

// Property wrapper with get & set accessors.
public Uri AquariumGraphic
{
    get => (Uri)GetValue(AquariumGraphicProperty);
    set => SetValue(AquariumGraphicProperty, value);
}

// Property-changed callback.
private static void OnUriChanged(DependencyObject dependencyObject, 
    DependencyPropertyChangedEventArgs e)
{
    // Some custom logic that runs on effective property value change.
    Uri newValue = (Uri)dependencyObject.GetValue(AquariumGraphicProperty);
    Debug.WriteLine($"OnUriChanged: {newValue}");
}
' Register a dependency property with the specified property name,
' property type, owner type, and property metadata. Store the dependency
' property identifier as a public static readonly member of the class.
Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty =
    DependencyProperty.Register(
        name:="AquariumGraphic",
        propertyType:=GetType(Uri),
        ownerType:=GetType(Aquarium),
        typeMetadata:=New FrameworkPropertyMetadata(
            defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"),
            flags:=FrameworkPropertyMetadataOptions.AffectsRender,
            propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged)))

' Property wrapper with get & set accessors.
Public Property AquariumGraphic As Uri
    Get
        Return CType(GetValue(AquariumGraphicProperty), Uri)
    End Get
    Set
        SetValue(AquariumGraphicProperty, Value)
    End Set
End Property

' Property-changed callback.
Private Shared Sub OnUriChanged(dependencyObject As DependencyObject,
                                e As DependencyPropertyChangedEventArgs)
    ' Some custom logic that runs on effective property value change.
    Dim newValue As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri)
    Debug.WriteLine($"OnUriChanged: {newValue}")
End Sub

Voir aussi