Delen via


XAML-laad- en afhankelijkheidseigenschappen (WPF .NET)

De WPF-implementatie (Windows Presentation Foundation) van de XAML-processor (Extensible Application Markup Language) is van nature afhankelijkheidseigenschap-bewust. Als zodanig gebruikt de XAML-processor WPF-eigenschappensysteemmethoden om XAML te laden en afhankelijkheidseigenschapskenmerken te verwerken, waarbij afhankelijkheidseigenschapswikkelaars volledig worden omzeild door gebruik te maken van WPF-eigenschappensysteemmethoden zoals GetValue en SetValue. Dus als u aangepaste logica toevoegt aan de eigenschap wrapper van uw aangepaste afhankelijkheidseigenschap, wordt deze niet aangeroepen door de XAML-processor wanneer een eigenschapswaarde is ingesteld in XAML.

Voorwaarden

In het artikel wordt ervan uitgegaan dat u basiskennis hebt van afhankelijkheidseigenschappen en dat u overzicht van eigenschappen van afhankelijkheden hebt gelezen. Als u de voorbeelden in dit artikel wilt volgen, helpt dit als u bekend bent met Extensible Application Markup Language (XAML) en weet hoe u WPF-toepassingen schrijft.

WPF XAML-laadprogrammaprestaties

Het is rekenkundig goedkoper voor de WPF XAML-processor om rechtstreeks SetValue aan te roepen om de waarde van een afhankelijkheidseigenschap in te stellen, in plaats van de eigenschap wrapper van een afhankelijkheidseigenschap te gebruiken.

Als de XAML-processor de eigenschapswikkelaar zou hebben gebruikt, zou het hele objectmodel van de backingcode alleen moeten worden afgeleid op basis van het type en de lidrelaties die in markup zijn aangegeven. Hoewel het type kan worden geïdentificeerd uit markeringen met behulp van een combinatie van xmlns- en assemblykenmerken, zou het identificeren van de leden, het bepalen welke leden kunnen worden ingesteld als een kenmerk en het omzetten van ondersteunde eigenschapswaardetypen, uitgebreide reflectie vereisen met behulp van PropertyInfo.

Het WPF-eigenschappensysteem onderhoudt een opslagtabel met afhankelijkheidseigenschappen die zijn geïmplementeerd op een bepaald DependencyObject afgeleid type. De XAML-processor gebruikt die tabel om de identificator van de afhankelijkheidseigenschap voor een afhankelijkheidseigenschap af te leiden. De identificatie van de afhankelijkheidseigenschap voor een afhankelijkheidseigenschap met de naam ABC is bijvoorbeeld ABCProperty. De XAML-processor kan de waarde van elke afhankelijkheidseigenschap efficiënt instellen door de SetValue methode aan te roepen voor het bijbehorende type met behulp van de id van de afhankelijkheidseigenschap.

Voor meer informatie over afhankelijkheidseigenschapswrappers, zie Aangepaste afhankelijkheidseigenschappen.

Gevolgen voor aangepaste afhankelijkheidseigenschappen

De WPF XAML-processor omzeilt eigenschapswikkelaars en roept rechtstreeks SetValue aan om een waarde voor een afhankelijkheidseigenschap in te stellen. Plaats dus geen extra logica in de set accessor van uw aangepaste afhankelijkheidseigenschap, omdat deze logica niet wordt uitgevoerd wanneer een eigenschapswaarde is ingesteld in XAML. De set-accessor mag alleen een SetValue aanroep bevatten.

Op dezelfde manier worden in de WPF XAML-processor aspecten die eigenschapswaarden ophalen de eigenschapswikkelaar overgeslagen en wordt GetValuedirect aangeroepen. Vermijd dus ook dat u extra logica in de get accessor van uw aangepaste afhankelijkheidseigenschap plaatst, omdat deze logica niet wordt uitgevoerd wanneer een eigenschapswaarde wordt gelezen in XAML. De get-accessor mag alleen een GetValue aanroep bevatten.

Voorbeeld van afhankelijkheidseigenschap met wrapper

In het volgende voorbeeld ziet u een aanbevolen definitie van de afhankelijkheidseigenschap met eigenschappenhulzen. De id van de afhankelijkheidseigenschap wordt opgeslagen als een public static readonly veld en de get en set-accessors bevatten geen code buiten de benodigde WPF-eigenschappensysteemmethoden die de waarde van de afhankelijkheidseigenschap terugzetten. Als u code hebt die moet worden uitgevoerd wanneer de waarde van uw afhankelijkheidseigenschap verandert, kunt u overwegen die code in de PropertyChangedCallback voor uw afhankelijkheidseigenschap te plaatsen. Voor meer informatie, zie Property-changed callbacks.

// 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

Zie ook