Dědičnost hodnot vlastností (WPF .NET)

Dědičnost hodnot vlastností je funkce systému vlastností WINDOWS Presentation Foundation (WPF) a vztahuje se na vlastnosti závislostí. Dědičnost hodnot vlastností umožňuje podřízeným prvkům ve stromu prvků získat hodnotu konkrétní vlastnosti z nejbližšího nadřazeného prvku. Vzhledem k tomu, že nadřazený prvek mohl také získat hodnotu vlastnosti prostřednictvím dědičnosti hodnoty vlastnosti, systém se potenciálně znovu vrátí do kořenového adresáře stránky.

Systém vlastností WPF ve výchozím nastavení neumožňuje dědičnost hodnot vlastností a dědičnost hodnot je neaktivní, pokud není výslovně povolená v metadatech vlastností závislostí. I když je povolena dědičnost hodnot vlastností, podřízený prvek dědí pouze hodnotu vlastnosti v případě, že chybí hodnota vyšší priority .

Důležité

Dokumentace k desktopové příručce pro .NET 7 a .NET 6 se právě připravuje.

Předpoklady

V článku se předpokládá základní znalost vlastností závislostí a že jste si přečetli přehled vlastností závislostí. Pokud chcete postupovat podle příkladů v tomto článku, pomůže vám to, pokud znáte jazyk XAML (Extensible Application Markup Language) a víte, jak psát aplikace WPF.

Dědičnost prostřednictvím stromu elementů

Dědičnost hodnot vlastností není stejný koncept jako dědičnost tříd v objektově orientovaném programování, kde odvozené třídy dědí členy základní třídy. Tento druh dědičnosti je také aktivní ve WPF, ačkoli v XAML zděděné vlastnosti základní třídy jsou vystaveny jako atributy elementů XAML, které představují odvozené třídy.

Dědičnost hodnot vlastností je mechanismus, kterým se hodnota vlastnosti závislosti šíří z nadřazených na podřízené prvky ve stromu prvků, které obsahují vlastnost. V kódu XAML je strom prvků viditelný jako vnořené prvky.

Následující příklad ukazuje vnořené elementy v XAML. WPF zaregistruje AllowDrop vlastnost závislosti na UIElement třídě s metadaty vlastností, která umožňuje dědičnost hodnot vlastností a nastaví výchozí hodnotu na false. Vlastnost AllowDrop závislosti existuje na Canvas, StackPanela Label prvky, protože všechny jsou odvozeny od UIElement. Vzhledem k tomu, závislost AllowDrop vlastnost je canvas1 nastavena na true, potomek stackPanel1 a label1 elementy dědí true jako jejich AllowDrop hodnotu.

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

Strom prvků můžete také vytvořit programově přidáním objektů elementů do podřízené kolekce elementů jiného objektu elementu. Dědičnost hodnot vlastností v době běhu pracuje s výsledným stromem objektů. V následujícím příkladu stackPanel2 je přidán do podřízené canvas2kolekce . label2 Podobně je přidán do podřízené stackPanel2kolekce . Vzhledem k tomu, závislost AllowDrop vlastnost je canvas2 nastavena na true, potomek stackPanel2 a label2 elementy dědí true jako jejich AllowDrop hodnotu.

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)

Praktické použití dědičnosti hodnot vlastností

Specifické vlastnosti závislosti WPF mají ve výchozím nastavení povolenou dědičnost hodnot, například AllowDrop a FlowDirection. Vlastnosti s povolenou dědičností hodnot jsou obvykle implementovány na základní třídy prvků uživatelského rozhraní, takže existují na odvozených třídách. Například vzhledem k tomu, že AllowDrop je implementována v UIElement základní třídě, tato závislost vlastnost existuje také na každém ovládacím prvku odvozeného z UIElement. WPF umožňuje dědičnost hodnot u vlastností závislostí, pro které je vhodné, aby uživatel nastavil hodnotu vlastnosti jednou u nadřazeného elementu a aby se tato hodnota vlastnosti šířil na potomky elementů ve stromu elementů.

Model dědičnosti hodnot vlastností přiřazuje hodnoty vlastností, zděděné i nezděděné podle priority hodnoty vlastnosti závislosti. Hodnota vlastnosti nadřazeného elementu se tedy použije pouze u podřízeného elementu, pokud vlastnost podřízeného elementu nemá vyšší prioritu, například místně nastavenou hodnotu nebo hodnotu získanou prostřednictvím stylů, šablon nebo datové vazby.

Vlastnost FlowDirection závislostí nastaví směr rozložení textových a podřízených prvků uživatelského rozhraní v rámci nadřazeného elementu. Obvykle byste očekávali, že směr toku textu a prvků uživatelského rozhraní na stránce bude konzistentní. Vzhledem k tomu, že dědičnost hodnot je povolena v metadatechFlowDirectionvlastnosti , hodnota musí být nastavena pouze jednou v horní části stromu elementů pro stránku. Ve výjimečných případech, kdy je pro stránku určená kombinace směrů toku, je možné u elementu ve stromu nastavit jiný směr toku přiřazením hodnoty místně nastavené. Nový směr toku se pak rozšíří do následnických prvků pod danou úrovní.

Vytvoření vlastní vlastnosti zděděné

Vlastní vlastnost závislostí můžete zdědit povolením Inherits vlastnosti v instanci FrameworkPropertyMetadataa následnou registrací vlastní vlastnosti závislosti v této instanci metadat. Ve výchozím nastavení Inherits je nastavena na false hodnotu in FrameworkPropertyMetadata. Zdědědění hodnoty vlastnosti má vliv na výkon, takže je nastaveno Inherits pouze v true případě, že je tato funkce potřebná.

Při registraci vlastnosti závislosti s povolenými Inherits v metadatech použijte metodu RegisterAttached popsanou v části Registrace připojené vlastnosti. Také přiřaďte vlastnost výchozí hodnotu tak, aby zděděná hodnota existuje. Můžete také chtít vytvořit obálku vlastností s get typem vlastníka a set přístupové objekty stejně jako u neapojené vlastnosti závislosti. Tímto způsobem můžete nastavit hodnotu vlastnosti pomocí obálky vlastnosti u vlastníka nebo odvozeného typu. Následující příklad vytvoří vlastnost závislosti s IsTransparentInherits povolenou a výchozí hodnotou false. Příklad také obsahuje obálku vlastností s get a set přístupovými objekty.

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

Připojené vlastnosti jsou koncepčně podobné globálním vlastnostem. Jejich hodnotu můžete zkontrolovat na libovolném DependencyObject a získat platný výsledek. Typickým scénářem připojených vlastností je nastavení hodnot vlastností u podřízených prvků a tento scénář je efektivnější, pokud je daná vlastnost implicitně přítomna jako připojená vlastnost pro každý DependencyObject prvek ve stromu.

Dědění hodnot vlastností přes hranice stromu

Dědičnost vlastností funguje procházením stromu prvků. Tento strom je často paralelní s logickým stromem. Při každém zahrnutí objektu základní úrovně WPF, například objektu Brushna úrovni kódu, který definuje strom elementů, jste vytvořili nesouvisený logický strom. Skutečný logický strom nepřesahuje koncepčně, Brushprotože logický strom je koncept na úrovni architektury WPF. Pomocné metody LogicalTreeHelper můžete použít k analýze a zobrazení rozsahu logického stromu. Dědičnost hodnoty vlastnosti je schopna předat zděděné hodnoty prostřednictvím nesouviseného logického stromu, ale pouze v případě, že zděděná vlastnost byla zaregistrována jako připojená vlastnost a neexistuje úmyslná hranice blokování dědičnosti, například Frame.

Poznámka:

I když se může zdát, že dědičnost hodnot vlastností může fungovat pro neapojené vlastnosti závislostí, chování dědičnosti pro neapojenou vlastnost prostřednictvím některých hranic prvků ve stromu modulu runtime není definováno. Kdykoli zadáte Inherits v metadatech vlastností, zaregistrujte své vlastnosti pomocí RegisterAttached.

Viz také