Tulajdonságérték öröklése

A tulajdonságérték-öröklés a Windows Presentation Foundation (WPF) tulajdonságrendszer egyik funkciója, amely függőségi tulajdonságokra vonatkozik. A tulajdonságérték-öröklés lehetővé teszi, hogy az elemfában lévő gyermekelemek egy adott tulajdonság értékét a legközelebbi szülőelemből szerezze be. Mivel egy szülőelem tulajdonságérték-örökléssel is beszerezhette a tulajdonságértékét, a rendszer valószínűleg visszatér az oldal gyökeréhez.

A WPF tulajdonságrendszer alapértelmezés szerint nem engedélyezi a tulajdonságértékek öröklését, és az értéköröklés inaktív, kivéve, ha kifejezetten engedélyezve van a függőségi tulajdonság metaadatok. Ha a tulajdonságérték öröklése engedélyezve van, a gyermekelem csak magasabb elsőbbségi érték hiányában örököl egy tulajdonságértéket.

Előfeltételek

A cikk feltételezi a függőségi tulajdonságok alapszintű ismeretét, és hogy elolvasta függőségi tulajdonságok áttekintését. A cikkben szereplő példák követéséhez segít, ha ismeri az Extensible Application Markup Language (XAML) nyelvet, és ismeri a WPF-alkalmazások írásának módját.

Öröklés elemfán keresztül

A tulajdonságértékek öröklése nem ugyanaz, mint az osztályöröklés az objektumorientált programozásban, ahol a származtatott osztályok öröklik az alaposztálytagokat. Az ilyen típusú öröklés a WPF-ben is aktív, bár az XAML-ben az örökölt alaposztály-tulajdonságok a származtatott osztályokat képviselő XAML-elemek attribútumaiként jelennek meg.

A tulajdonságérték öröklése az a mechanizmus, amellyel a függőségi tulajdonság értéke a szülőtől a gyermekelemekig terjed a tulajdonságot tartalmazó elemek fáján belül. Az XAML jelölésben az elemek fája beágyazott elemekként látható.

Az alábbi példa az XAML beágyazott elemeit mutatja be. A WPF a AllowDrop osztály UIElement függőségi tulajdonságát olyan metaadat- regisztrálja, amely lehetővé teszi a tulajdonságérték öröklési, és az alapértelmezett értéket falseértékre állítja. A AllowDrop függőségi tulajdonság Canvas, StackPanelés Label elemeken található, mivel ezek mindegyike UIElementszármazik. Mivel a AllowDropcanvas1 függőségi tulajdonsága true-re van állítva, a leszármazott stackPanel1 és label1 elemek öröklik a true-t, mint AllowDrop értéket.

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

Az elemek fáját programozott módon is létrehozhatja, ha elemobjektumokat ad hozzá egy másik elemobjektum gyermekelemgyűjteményéhez. Futásidőben a tulajdonságérték öröklése az eredményül kapott objektumfán működik. Az alábbi példában a stackPanel2 hozzáadódik a canvas2-hez. Hasonlóképpen, label2 is hozzáadódik a stackPanel2gyermekgyűjteményéhez. Mivel a AllowDropcanvas2 függőségi tulajdonsága true-re van állítva, a leszármazott stackPanel2 és label2 elemek öröklik a true-t, mint AllowDrop értéket.

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)

A tulajdonságérték öröklésének gyakorlati alkalmazásai

Bizonyos WPF-függőségi tulajdonságok alapértelmezés szerint engedélyezve vannak az értéköröklésben, például AllowDrop és FlowDirection. Az alapértelmezés szerint engedélyezett értéköröklésű tulajdonságok általában alapszintű felhasználói felületi elemosztályokon vannak implementálva, így származtatott osztályokon léteznek. Mivel például AllowDrop az UIElement alaposztályon van implementálva, ez a függőségi tulajdonság az UIElementszármazó összes vezérlőn is létezik. A WPF lehetővé teszi az értéköröklést a függőségi tulajdonságokon, amelyek esetében a felhasználó számára kényelmes, ha egyszer beállítja a tulajdonságértéket egy szülőelemen, és a tulajdonság értékét az elemfa leszármazott elemeire propagálja.

A tulajdonságérték-öröklési modell mind az örökölt, mind a nem örökölt tulajdonságértékeket rendeli hozzá a függőségi tulajdonság értékelsősége szerint. A szülőelem tulajdonságértéke tehát csak akkor lesz alkalmazva egy gyermekelemre, ha a gyermekelem tulajdonsága nem rendelkezik magasabb prioritási értékkel, például helyileg beállított értékkel, illetve stílusokkal, sablonokkal vagy adatkötéssel kapott értékkel.

A FlowDirection függőség tulajdonság beállítja a szöveg és a gyermek felhasználói felület elemeinek elrendezési irányát egy szülőelemen belül. Általában elvárható, hogy a szöveg és a felhasználói felület elemeinek folyamatiránya konzisztens legyen. Mivel az értéköröklés engedélyezve van tulajdonságában, egy értéket csak egyszer kell beállítani egy lap elemfája tetején. Abban a ritka esetben, amikor a folyamatirányok keveréke egy laphoz van szánva, egy helyileg beállított érték hozzárendelésével másik folyamatirány állítható be a fa egy elemére. Az új folyásirány ezután továbbterjed az adott szint alatti leszármazott elemekre.

Egyéni tulajdonság örökölhetővé tétele

Az egyéni függőségi tulajdonság örökölhetővé tételéhez engedélyezze a Inherits tulajdonságot egy FrameworkPropertyMetadata-példányban, majd regisztrálja az egyéni függőségi tulajdonságot az adott metaadatpéldányban. Az alapértelmezett beállítás szerint a Inherits a false értékre van állítva a FrameworkPropertyMetadata-ban. A tulajdonságérték örökölhetővé tétele hatással van a teljesítményre, ezért csak akkor állítsa Inheritstrue, ha erre a funkcióra van szükség.

Amikor egy függőségi tulajdonságot regisztrál a Inherits metaadatokban történő engedélyezéssel, használja a RegisterAttached metódust a 'Csatolt tulajdonságregisztrálása' című útmutatóban leírtak szerint. Emellett rendeljen hozzá egy alapértelmezett értéket a tulajdonsághoz, hogy örökölhető érték legyen. Érdemes lehet olyan tulajdonságburkolót is létrehozni, amely get és set hozzáférőkkel rendelkezik a tulajdonos típusán, ugyanúgy, mint egy nem csatlakoztatott függőségi tulajdonság esetében. Így a tulajdonság értékét a tulajdonos vagy a származtatott típus tulajdonságburkolójának segítségével állíthatja be. Az alábbi példa létrehoz egy IsTransparentnevű függőségi tulajdonságot, amely engedélyezve van Inherits, és alapértelmezett értéke false. A példa egy get és set hozzáférési metódusokkal rendelkező tulajdonságburkolót is tartalmaz.

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

A csatolt tulajdonságok fogalmilag hasonlóak a globális tulajdonságokhoz. Értéküket bármelyik DependencyObject-on ellenőrizheti, és érvényes eredményt kaphat. A csatolt tulajdonságok tipikus forgatókönyve a gyermekelemek tulajdonságértékeinek beállítása, és ez a forgatókönyv hatékonyabb, ha a szóban forgó tulajdonság implicit módon csatolt tulajdonságként van jelen a fa minden egyes DependencyObject elemén.

Tulajdonságok öröklése a fastruktúrák határain keresztül

A tulajdonsági öröklés az elemek fájának bejárásával történik. Ez a fa gyakran párhuzamos a logikai fával. Ha azonban egy WPF magszintű objektumot, például egy Brush-t, is belefoglal az elemfát meghatározó jelölőnyelvbe, ezzel megszakított logikai fát hoz létre. A valódi logikai fa elméletileg nem terjed ki a Brush, mivel a logikai fa egy WPF keretrendszerszintű fogalom. A LogicalTreeHelper segítő módszereivel elemezheti és megtekintheti a logikai fa kiterjedésének mértékét. A tulajdonságérték-öröklés nem folytonos logikai fán keresztül képes átadni az örökölt értékeket, de csak akkor, ha az örökölhető tulajdonság csatolt tulajdonságként lett regisztrálva, és nincs szándékos öröklést blokkoló határ, például Frame.

Megjegyzés:

Bár a tulajdonságérték öröklése úgy tűnhet, hogy nem csatolt függőségi tulajdonságok esetében működik, a futtatókörnyezeti fa egyes elemhatárain keresztüli nem csatolt tulajdonságok öröklési viselkedése nincs meghatározva. Amikor a tulajdonság metaadataiban meg van adva a Inherits, regisztrálja a tulajdonságokat a RegisterAttachedalkalmazásával.

Lásd még