Dela via


Egenskapsvärdesarv (WPF .NET)

Arv av egenskapsvärde är en funktion i WPF-egenskapssystemet (Windows Presentation Foundation) och gäller beroendeegenskaper. Med arv av egenskapsvärde kan underordnade element i ett träd med element hämta värdet för en viss egenskap från närmaste överordnade element. Eftersom ett överordnat element också kan ha fått sitt egenskapsvärde via arv av egenskapsvärde, återkommer systemet eventuellt till rot på sidan.

WPF-egenskapssystemet aktiverar inte arv av egenskapsvärden som standard, och värdesarv är inaktiverat om det inte specifikt aktiveras i beroendeegenskapens metadata. Även om arv av egenskapsvärde är aktiverat ärver ett underordnat element bara ett egenskapsvärde i avsaknad av ett högre prioritet värde.

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.

Arv genom ett elementträd

Arv av egenskapsvärde är inte samma begrepp som klassarv i objektorienterad programmering, där härledda klasser ärver basklassmedlemmar. Den typen av arv är också aktivt i WPF, men i XAML exponeras de ärvda basklassegenskaperna som attribut för XAML-element som representerar härledda klasser.

Arv av egenskapsvärde är den mekanism med vilken ett beroendeegenskapsvärde sprids från överordnade till underordnade element i ett träd med element som innehåller egenskapen. I XAML-markering visas ett träd med element som kapslade element.

I följande exempel visas kapslade element i XAML. WPF registrerar beroendeegenskapen AllowDropUIElement-klassen med metadata som möjliggör att egenskapsvärdet ärvs och anger standardvärdet till false. Den AllowDrop beroendeegenskapen finns på elementen Canvas, StackPaneloch Label eftersom alla härleds från UIElement. Eftersom den AllowDrop beroendeegenskapen på canvas1 är inställd på trueärver de underordnade stackPanel1- och label1-elementen true som deras AllowDrop värde.

<Canvas x:Name="canvas1" Grid.Column="0" Margin="20" Background="Orange" AllowDrop="True">
    <StackPanel Name="stackPanel1" Margin="20" Background="Green">
        <Label Name="label1" Margin="20" Height="40" Width="40" Background="Blue"/>
    </StackPanel>
</Canvas>

Du kan också skapa ett träd med element programmatiskt genom att lägga till elementobjekt i den underordnade elementsamlingen för ett annat elementobjekt. Vid körning sker arv av egenskapsvärde på det resulterande objektträdet. I följande exempel tilläggs till i den underordnade -samlingen för . På liknande sätt läggs label2 till i barnsamlingen av stackPanel2. Eftersom beroendeegenskapen AllowDrop för canvas2 är inställd på true, ärver de underordnade stackPanel2- och label2-elementen true som sitt AllowDrop-värde.

Canvas canvas2 = new()
{
    AllowDrop = true
};
StackPanel stackPanel2 = new();
Label label2 = new();
canvas2.Children.Add(stackPanel2);
stackPanel2.Children.Add(label2);
Dim canvas2 As New Canvas With {
    .AllowDrop = True
}
Dim stackPanel2 As New StackPanel()
Dim label2 As New Label()
canvas2.Children.Add(stackPanel2)
stackPanel2.Children.Add(label2)

Praktiska tillämpningar av arv av egenskapsvärde

Specifika WPF-beroendeegenskaper har värdearv aktiverat som standard, till exempel AllowDrop och FlowDirection. Vanligtvis implementeras egenskaper med värdearv aktiverat som standard på grundläggande UI-elementklasser, så de finns i härledda klasser. Eftersom AllowDrop till exempel implementeras på den UIElement basklassen finns den beroendeegenskapen också på varje kontroll som härleds från UIElement. WPF aktiverar värdearv på beroendeegenskaper som det är praktiskt för en användare att ange egenskapsvärdet en gång på ett överordnat element och låta egenskapsvärdet spridas till underordnade element i elementträdet.

Arvsmodellen för egenskapsvärden tilldelar egenskapsvärden, både ärvda och icke-ärvda, enligt beroendeegenskapens värdeordning. Därför tillämpas ett överordnat elements egenskapsvärde bara på ett underordnat element, om den underordnade elementegenskapen inte har ett högre prioritetsvärde, till exempel ett lokalt angivet värde eller ett värde som hämtas via format, mallar eller databindning.

Egenskapen FlowDirection beroende anger layoutriktningen för text- och underordnade gränssnittselement i ett överordnat element. Normalt kan du förvänta dig att flödesriktningen för text- och användargränssnittselement på en sida är konsekvent. Eftersom värdearv är aktiverat i egenskapen metadata av FlowDirectionbehöver ett värde bara anges en gång överst i elementträdet för en sida. I sällsynta fall där en blandning av flödesriktningar är avsedd för en sida kan en annan flödesriktning anges för ett element i trädet genom att tilldela ett lokalt angivet värde. Den nya flödesriktningen sprids sedan till underordnade element under den nivån.

Göra en anpassad egenskap ärverbar

Du kan göra en anpassad beroendeegenskap ärverbar genom att aktivera egenskapen Inherits i en instans av FrameworkPropertyMetadataoch sedan registrera din anpassade beroendeegenskap med den metadatainstansen. Som standard är Inherits inställt på false i FrameworkPropertyMetadata. Att göra ett egenskapsvärde ärverbart påverkar prestanda, så ange bara Inherits till true om den funktionen behövs.

När du registrerar en beroendeegenskap med Inherits aktiverad i metadata använder du metoden RegisterAttached enligt beskrivningen i Registrera en bifogad egenskap. Tilldela också ett standardvärde till egenskapen så att det finns ett ärvbart värde. Du kanske också vill skapa en property wrapper med get och set-accessorer på ägartypen, precis som du skulle göra för en icke-ansluten beroendeegenskap. På så sätt kan du ange egenskapsvärdet med hjälp av egenskapsomslutningen på en ägare eller härledd typ. I följande exempel skapas en beroendeegenskap med namnet IsTransparent, med Inherits aktiverat och standardvärdet false. Exemplet innehåller även en egenskapsinpackning med get och set-accessorer.

public class Canvas_IsTransparentInheritEnabled : Canvas
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata
    // (default value is 'false' and property value inheritance is enabled).
    public static readonly DependencyProperty IsTransparentProperty =
        DependencyProperty.RegisterAttached(
            name: "IsTransparent",
            propertyType: typeof(bool),
            ownerType: typeof(Canvas_IsTransparentInheritEnabled),
            defaultMetadata: new FrameworkPropertyMetadata(
                defaultValue: false,
                flags: FrameworkPropertyMetadataOptions.Inherits));

    // Declare a get accessor method.
    public static bool GetIsTransparent(Canvas element)
    {
        return (bool)element.GetValue(IsTransparentProperty);
    }

    // Declare a set accessor method.
    public static void SetIsTransparent(Canvas element, bool value)
    {
        element.SetValue(IsTransparentProperty, value);
    }

    // For convenience, declare a property wrapper with get/set accessors.
    public bool IsTransparent
    {
        get => (bool)GetValue(IsTransparentProperty);
        set => SetValue(IsTransparentProperty, value);
    }
}
Public Class Canvas_IsTransparentInheritEnabled
    Inherits Canvas

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata
    ' (default value is 'false' and property value inheritance is enabled).
    Public Shared ReadOnly IsTransparentProperty As DependencyProperty =
        DependencyProperty.RegisterAttached(
            name:="IsTransparent",
            propertyType:=GetType(Boolean),
            ownerType:=GetType(Canvas_IsTransparentInheritEnabled),
            defaultMetadata:=New FrameworkPropertyMetadata(
                defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.[Inherits]))

    ' Declare a get accessor method.
    Public Shared Function GetIsTransparent(element As Canvas) As Boolean
        Return element.GetValue(IsTransparentProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean)
        element.SetValue(IsTransparentProperty, value)
    End Sub

    ' For convenience, declare a property wrapper with get/set accessors.
    Public Property IsTransparent As Boolean
        Get
            Return GetValue(IsTransparentProperty)
        End Get
        Set(value As Boolean)
            SetValue(IsTransparentProperty, value)
        End Set
    End Property
End Class

Bifogade egenskaper liknar de globala egenskaperna konceptuellt. Du kan kontrollera deras värde på alla DependencyObject och få ett giltigt resultat. Det typiska scenariot för bifogade egenskaper är att ange egenskapsvärden för underordnade element, och det scenariot är effektivare om egenskapen i fråga implicit finns som en bifogad egenskap för varje DependencyObject element i trädet.

Att ärva egenskapsvärden över trädgränser

Egenskapsarv fungerar genom att gå igenom ett träd med element. Det här trädet är ofta parallellt med det logiska trädet. Men när du inkluderar ett WPF-objekt på kärnnivå, till exempel en Brush, i markering som definierar ett elementträd, har du skapat ett diskontinuerligt logiskt träd. Ett sant logiskt träd sträcker sig inte konceptuellt genom Brush, eftersom det logiska trädet är ett WPF-ramverksnivåbegrepp. Du kan använda hjälpmetoderna för LogicalTreeHelper för att analysera och visa omfattningen av ett logiskt träd. Arv av egenskapsvärde kan skicka ärvda värden genom ett diskontinuerligt logiskt träd, men bara om den ärvbara egenskapen registrerades som en bifogad egenskap och det inte finns någon avsiktlig gräns som blockerar arv, till exempel en Frame.

Not

Arv av egenskapsvärden kan verka fungera för icke-anslutna beroendeegenskaper, men arvsbeteendet för en icke-ansluten egenskap genom vissa elementgränser i körningsträdet är odefinierat. När du anger Inherits i egenskapsmetadata registrerar du dina egenskaper med hjälp av RegisterAttached.

Se även