Dela via


XAML-inläsnings- och beroendeegenskaper (WPF .NET)

Windows Presentation Foundation-implementeringen (WPF) av XAML-processorn (Extensible Application Markup Language) är beroendeegenskapsmedveten. Därför använder XAML-processorn WPF-egenskapssystemmetoder för att läsa in XAML och bearbeta attribut för beroendeegenskaper och kringgår helt beroendeegenskapsomslutningar med hjälp av WPF-egenskapssystemmetoder som GetValue och SetValue. Så om du lägger till anpassad logik i egenskapsomslutningen för din anpassade beroendeegenskap anropas den inte av XAML-processorn när ett egenskapsvärde anges i XAML.

Förutsättningar

Artikeln förutsätter grundläggande kunskaper om beroendeegenskaper och att du har läst Översikt över beroendeegenskaper. Om du vill följa exemplen i den här artikeln hjälper det om du är bekant med XAML (Extensible Application Markup Language) och vet hur du skriver WPF-program.

WPF XAML-inläsningsprestanda

Det är beräkningsmässigt billigare för WPF XAML-processorn att direkt anropa SetValue för att ange värdet för en beroendeegenskap i stället för att använda egenskapsomslutningen för en beroendeegenskap.

Om XAML-processorn använde egenskapsomslutningen skulle det kräva att hela objektmodellen för stödkoden härleds baserat på typen och de medlemsrelationer som specificeras i markeringen. Även om typen kan identifieras från markering med hjälp av en kombination av xmlns- och sammansättningsattribut, skulle processen att identifiera medlemmar, avgöra vilka medlemmar som kan anges som ett attribut och att fastställa stödda egenskapsvärdetyper kräva omfattande reflektion med hjälp av PropertyInfo.

WPF-egenskapssystemet har en lagringstabell med beroendeegenskaper som implementeras på en viss DependencyObject härledd typ. XAML-processorn använder den tabellen för att härleda beroendeegenskapsidentifieraren för en beroendeegenskap. Enligt konventionen är beroendeegenskapsidentifieraren för en beroendeegenskap med namnet ABCABCProperty. XAML-processorn kan effektivt ange värdet för en beroendeegenskap genom att anropa metoden SetValue för dess innehållande typ med hjälp av beroendeegenskapsidentifieraren.

Mer information om beroendeegenskapsomslag hänvisas till Anpassade beroendeegenskaper.

Konsekvenser för anpassade beroendeegenskaper

WPF XAML-processorn kringgår egenskapsomslutningar och anropar direkt SetValue för att ange ett beroendeegenskapsvärde. Undvik därför att lägga till någon extra logik i set-åtkomstorn för din anpassade beroendeegenskap eftersom den logiken inte körs när ett egenskapsvärde anges i XAML. set-åtkomsten får bara innehålla ett SetValue-anrop.

På samma sätt finns det aspekter av WPF XAML-processorn som vid hämtning av egenskapsvärden kringgår egenskapsomslutningen och anropar direkt GetValue. Undvik därför att lägga in extra logik i get-åtkomstfunktionen för din anpassade beroendeegenskap eftersom den logiken inte körs när ett egenskapsvärde läses i XAML. get-åtkomsten får bara innehålla ett GetValue-anrop.

Beroendeegenskap med omslutningsexempel

I följande exempel visas en rekommenderad beroendeegenskapsdefinition med egenskapsomslutningar. Beroendeegenskapsidentifieraren lagras som ett public static readonly fält, och get- och set-accessorerna innehåller ingen kod utöver de nödvändiga WPF-egenskapssystemmetoderna som stöder värdet för beroendeegenskapen. Om du har kod som måste köras när värdet för beroendeegenskapen ändras bör du överväga att placera koden i PropertyChangedCallback för beroendeegenskapen. Mer information finns i Återanrop vid ändrad egenskap.

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

Se även