Dela via


Översikt över beroendeegenskaper (WPF .NET)

Windows Presentation Foundation (WPF) tillhandahåller en uppsättning tjänster som kan användas för att utöka funktionerna i en typs -egenskap. Tillsammans kallas dessa tjänster för WPF-egenskapssystemet. En egenskap som backas upp av WPF-egenskapssystemet kallas för en beroendeegenskap. Den här översikten beskriver WPF-egenskapssystemet och funktionerna i en beroendeegenskap, inklusive hur du använder befintliga beroendeegenskaper i XAML och i kod. Den här översikten innehåller även särskilda aspekter av beroendeegenskaper, till exempel metadata för beroendeegenskap och hur du skapar en egen beroendeegenskap i en anpassad klass.

Förutsättningar

Den här artikeln förutsätter grundläggande kunskaper om .NET-typsystemet och objektorienterad programmering. Om du vill följa exemplen i den här artikeln hjälper det dig att förstå XAML och veta hur du skriver WPF-program. För mer information, se Självstudie: Skapa en ny WPF-app med .NET.

Beroendeegenskaper och CLR-egenskaper

WPF-egenskaper exponeras vanligtvis som standardegenskaper för .NET . Du kan interagera med dessa egenskaper på en grundläggande nivå och aldrig veta att de implementeras som en beroendeegenskap. Kunskaper om vissa eller alla funktioner i WPF-egenskapssystemet hjälper dig dock att dra nytta av dessa funktioner.

Syftet med beroendeegenskaper är att tillhandahålla ett sätt att beräkna värdet för en egenskap baserat på värdet för andra indata, till exempel:

  • Systemegenskaper, till exempel teman och användarinställningar.
  • Mekanismer för just-in-time-egenskapsbestämning, till exempel databindning och animeringar/storyboards.
  • Mallar med flera användningsområden, till exempel resurser och formatmallar.
  • Värden som är kända via överordnade och underordnade relationer med andra element i elementträdet.

Dessutom kan en beroendeegenskap tillhandahålla:

  • Fristående validering.
  • Standardvärden.
  • Återanrop som övervakar ändringar i andra egenskaper.
  • Ett system som kan tvinga fram egenskapsvärden baserat på körningsinformation.

Härledda klasser kan ändra vissa egenskaper för en befintlig egenskap genom att åsidosätta metadata för en beroendeegenskap i stället för att åsidosätta den faktiska implementeringen av befintliga egenskaper eller skapa nya egenskaper.

I SDK-referensen kan du identifiera en beroendeegenskap genom att det finns ett avsnitt om beroendeegenskapsinformation på den hanterade referenssidan för den egenskapen. Sektionen för beroendeegenskapsinformation innehåller en länk till fältet för identifieraren DependencyProperty för den beroendeegenskapen. Den innehåller även en lista över metadataalternativ för den egenskapen, åsidosättningsinformation per klass och annan information.

Beroendeegenskaper understödjer CLR-egenskaper

Beroendeegenskaper och WPF-egenskapssystemet utökar egenskapsfunktionaliteten genom att tillhandahålla en typ som understödjer en egenskap, som ett alternativ till det vanliga mönstret för att understödja en egenskap med ett privat fält. Namnet på den här typen är DependencyProperty. Den andra viktiga typen som definierar WPF-egenskapssystemet är DependencyObject, som definierar basklassen som kan registrera och äga en beroendeegenskap.

Här är några vanliga terminologi:

  • Beroendeegenskapen, som är en egenskap som stöds av en DependencyProperty.

  • Beroendeegenskapsidentifierare, som är en DependencyProperty instans som erhålls som ett returvärde när du registrerar en beroendeegenskap och sedan lagras som en statisk medlem i en klass. Många av API:erna som interagerar med WPF-egenskapssystemet använder beroendeegenskapsidentifieraren som en parameter.

  • CLR "wrapper", som är get och set implementeringar för egenskapen. Dessa implementeringar innehåller beroendeegenskapsidentifieraren genom att använda den i anropen GetValue och SetValue. På så sätt tillhandahåller WPF-egenskapssystemet stöd för egenskapen.

I följande exempel definieras beroendeegenskapen IsSpinning för att visa relationen mellan identifieraren DependencyProperty och egenskapen som den stöder.

public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register(
    "IsSpinning", typeof(bool),
    typeof(MainWindow)
    );

public bool IsSpinning
{
    get => (bool)GetValue(IsSpinningProperty);
    set => SetValue(IsSpinningProperty, value);
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
    DependencyProperty.Register("IsSpinning", GetType(Boolean), GetType(MainWindow))

Public Property IsSpinning As Boolean
    Get
        Return GetValue(IsSpinningProperty)
    End Get
    Set(value As Boolean)
        SetValue(IsSpinningProperty, value)
    End Set
End Property

Namngivningskonventionen för egenskapen och dess stödfält DependencyProperty är viktig. Namnet på fältet är alltid namnet på egenskapen, med suffixet Property bifogat. Mer information om den här konventionen och orsakerna till den finns i Anpassade beroendeegenskaper.

Ange egenskapsvärden

Du kan ange egenskaper antingen i kod eller i XAML.

Ange egenskapsvärden i XAML

I följande XAML-exempel anges bakgrundsfärgen för en knapp till röd. Strängvärdet för XAML-attributet är typkonverterat av WPF XAML-parsern till en WPF-typ. I den genererade koden är WPF-typen en Color, via en SolidColorBrush.

<Button Content="I am red" Background="Red"/>

XAML stöder flera syntaxformulär för att ange egenskaper. Vilken syntax som ska användas för en viss egenskap beror på den värdetyp som en egenskap använder och andra faktorer, till exempel förekomsten av en typkonverterare. För mer information om XAML-syntax för att ange egenskaper, se XAML i WPF och XAML-syntax i detalj.

I följande XAML-exempel visas en annan knappbakgrund som använder syntax för egenskapselement i stället för attributsyntax. I stället för att ange en enkel solid färg anger XAML knappen Background egenskap till en bild. Ett element representerar den bilden och ett attribut för det kapslade elementet anger bildens källa.

<Button Content="I have an image background">
    <Button.Background>
        <ImageBrush ImageSource="stripes.jpg"/>
    </Button.Background>
</Button>

Ange egenskaper i kod

Att ange värden för beroendeegenskap i kod är vanligtvis bara ett anrop till den set-implementation som exponeras av CLR:s "wrapper".

Button myButton = new();
myButton.Width = 200.0;
Dim myButton As New Button With {
    .Width = 200.0
}

Att få ett egenskapsvärde är i huvudsak ett anrop till den "wrapper"-implementeringen av get.

double whatWidth = myButton.Width;
Dim whatWidth As Double = myButton.Width

Du kan också anropa egenskapssystemets API:er GetValue och SetValue direkt. Att anropa API:erna direkt är lämpligt för vissa scenarier, men vanligtvis inte när du använder befintliga egenskaper. Vanligtvis är wrappers mer praktiska och ger bättre exponering av egenskapen för utvecklarverktyg.

Egenskaper kan också anges i XAML och sedan nås senare i kod, via bakomliggande kod. För mer information, se Code-behind och XAML i WPF.

Egenskapsfunktioner som tillhandahålls av en beroendeegenskap

Till skillnad från en egenskap som backas upp av ett fält utökar en beroendeegenskap funktionerna för en egenskap. Ofta representerar eller stöder den tillagda funktionen någon av dessa funktioner:

Resurser

Du kan ange ett beroendeegenskapsvärde genom att referera till en resurs. Resurser anges vanligtvis som Resources egenskapsvärde för ett sidrotselement eller för applikationen, eftersom dessa platser ger praktisk åtkomst till resursen. I det här exemplet definierar vi en SolidColorBrush resurs:

<StackPanel.Resources>
    <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</StackPanel.Resources>

Nu när resursen har definierats kan vi referera till resursen för att ange ett värde för egenskapen Background:

<Button Background="{DynamicResource MyBrush}" Content="I am gold" />

I WPF XAML kan du använda antingen en statisk eller dynamisk resursreferens. Den här resursen refereras som en DynamicResource-. En dynamisk resursreferens kan bara användas för att ange en beroendeegenskap, så det är specifikt den dynamiska resursreferensanvändning som aktiveras av WPF-egenskapssystemet. Mer information finns i XAML-resurser.

Not

Resurser behandlas som ett lokalt värde, vilket innebär att om du anger ett annat lokalt värde eliminerar du resursreferensen. För mer information, se beroendeegenskapens värdeföreträde.

Databindning

En beroendeegenskap kan referera till ett värde via databindning. Databindning fungerar via en specifik syntax för markeringstillägg i XAML eller det Binding objektet i koden. Med databindning skjuts bestämningen av det slutliga egenskapsvärdet upp till körningstiden, då värdet hämtas från en datakälla.

I följande exempel anges egenskapen Content för en Buttonmed hjälp av en bindning som deklarerats i XAML. Bindningen använder en ärvd datakontext och en XmlDataProvider datakälla (visas inte). Bindningen i sig specificerar källegenskapen inom datakällan med XPath.

<Button Content="{Binding Source={StaticResource TestData}, XPath=test[1]/@text}"/>

Not

Bindningar behandlas som ett lokalt värde, vilket innebär att om du anger ett annat lokalt värde eliminerar du bindningen. Mer information finns i egenskapen Dependency value precedence.

Beroendeegenskaper, eller klassen DependencyObject, stöder inte internt INotifyPropertyChanged för meddelanden om ändringar i DependencyObject källegenskapsvärde för databindningsåtgärder. Mer information om hur du skapar egenskaper för användning i databindning som kan rapportera ändringar till ett databindningsmål finns i Översikt över databindning.

Stilar

Format och mallar är övertygande skäl att använda beroendeegenskaper. Format är särskilt användbara för att ange egenskaper som definierar programmets användargränssnitt. Formatmallar definieras vanligtvis som resurser i XAML. Formatmallar interagerar med egenskapssystemet eftersom de vanligtvis innehåller inställare för vissa egenskaper och utlösare som ändrar ett egenskapsvärde beroende på körningsegenskapens värde för en annan egenskap.

I följande exempel skapas ett enkelt format, som skulle definieras i en Resources ordlista (visas inte). Sedan appliceras stilen direkt på egenskapen Style för en Button. Settern i formatet anger egenskapen Background för en formaterad Button till grön.

<Style x:Key="GreenButtonStyle">
    <Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}" Content="I am green"/>

Mer information finns i Formatering och mallning.

Animationer

Beroendeegenskaper kan animeeras. När en tillämpad animering körs har det animerade värdet högre prioritet än något annat egenskapsvärde, inklusive ett lokalt värde.

I följande exempel animerar egenskapen Background för en Button. Tekniskt sett anger egenskapselementsyntaxen ett tomt SolidColorBrush som Background, och egenskapen Color för SolidColorBrush blir animerad.

<Button Content="I am animated">
    <Button.Background>
        <SolidColorBrush x:Name="AnimBrush"/>
    </Button.Background>
    <Button.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation
                        Storyboard.TargetName="AnimBrush" 
                        Storyboard.TargetProperty="(SolidColorBrush.Color)"
                        From="Blue" To="White" Duration="0:0:1" 
                        AutoReverse="True" RepeatBehavior="Forever" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>

Mer information om hur du animerar egenskaper finns i översikten över animering och Storyboards.

Åsidosättningar av metadata

Du kan ändra specifika beteenden för en beroendeegenskap genom att åsidosätta dess metadata när du härleder från klassen som ursprungligen registrerade beroendeegenskapen. Övergripande metadata förlitar sig på DependencyProperty identifierare och kräver inte omimplementering av egenskapen. Metadataändringen hanteras internt av egenskapssystemet. Varje klass innehåller potentiellt enskilda metadata för alla egenskaper som ärvts från basklasser per typ.

I följande exempel åsidosätts metadata för en DefaultStyleKey beroendeegenskap. Att åsidosätta metadata för den här beroendeegenskapen är en del av ett implementeringsmönster för att skapa kontroller som kan använda standardformat från teman.

public class SpinnerControl : ItemsControl
{
    static SpinnerControl() => DefaultStyleKeyProperty.OverrideMetadata(
            typeof(SpinnerControl),
            new FrameworkPropertyMetadata(typeof(SpinnerControl))
        );
}
Public Class SpinnerControl
    Inherits ItemsControl
    Shared Sub New()
        DefaultStyleKeyProperty.OverrideMetadata(GetType(SpinnerControl), New FrameworkPropertyMetadata(GetType(SpinnerControl)))
    End Sub
End Class

Mer information om att åsidosätta eller komma åt metadata för beroendeegenskaper finns i Åsidosätt metadata för en beroendeegenskap.

Egenskapsvärdets arv

Ett element kan ärva värdet för en beroendeegenskap från dess överordnade i objektträdet.

Not

Arvsbeteendet för egenskapsvärden är inte globalt aktiverat för alla beroendeegenskaper, eftersom beräkningstiden för arv påverkar prestanda. Arv av egenskapsvärde är vanligtvis bara aktiverat i scenarier som tyder på tillämplighet. Du kan kontrollera om en beroendeegenskap ärver genom att titta på avsnittet Dependency Property Information för beroendeegenskapen i SDK-referensen.

I följande exempel visas en bindning som innehåller egenskapen DataContext för att ange bindningens källa. Bindningar i underordnade objekt behöver därför inte ange källan och kan använda det ärvda värdet från DataContext i det överordnade StackPanel-objektet. Eller så kan ett underordnat objekt direkt ange sina egna DataContext eller en Source i Bindingoch inte använda det ärvda värdet.

<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource TestData}}">
    <Button Content="{Binding XPath=test[2]/@text}"/>
</StackPanel>

För mer information, se egenskapsvärdesarv .

WPF-designerintegrering

Anpassade kontroller med egenskaper implementerade som beroendeegenskaper integreras väl med WPF Designer för Visual Studio. Ett exempel är möjligheten att redigera direkta och anslutna beroendeegenskaper i fönstret Egenskaper. Mer information finns i Kontrollredigeringsöversikt.

Prioritet för beroendeegenskapsvärde

Alla egenskapsbaserade indata i WPF-egenskapssystemet kan ange värdet för en beroendeegenskap. Värdehierarki för beroendeegenskaper existerar för att de olika scenarierna för hur egenskaper får sina värden ska interagera på ett förutsägbart sätt.

Notera

SDK-dokumentationen använder ibland termen "lokalt värde" eller "lokalt angivet värde" när du diskuterar beroendeegenskaper. Ett lokalt angivet värde är ett egenskapsvärde som anges direkt på en objektinstans i kod eller som ett elementattribut i XAML.

Nästa exempel innehåller ett format som gäller för egenskapen Background för valfri knapp, men anger en knapp med en lokalt inställd Background egenskap. Tekniskt sett har den knappen sin Background egenskap inställd två gånger, även om endast ett värde gäller – värdet med högsta prioritet. Ett lokalt angivet värde har högst prioritet, förutom en animering som körs, som inte finns här. Den andra knappen använder därför det lokalt inställda värdet för egenskapen Background, i stället för formatuppsättningsvärdet. Den första knappen har inget lokalt värde, eller något annat värde med högre prioritet än en formatuppsättning, och använder därför formatuppsättningsvärdet för egenskapen Background.

<StackPanel>
    <StackPanel.Resources>
        <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Orange"/>
        </Style>
    </StackPanel.Resources>
    <Button>I am styled orange</Button>
    <Button Background="Pink">I am locally set to pink (not styled orange)</Button>
</StackPanel>

Varför har beroendeegenskap företräde?

Lokalt angivna värden har företräde framför formatuppsättningsvärden, som stöder lokal kontroll över elementegenskaper. För mer information, se beroendeegenskapens värdeföreträde.

Not

Ett antal egenskaper som definierats för WPF-element är inte beroendeegenskaper, eftersom beroendeegenskaper vanligtvis bara implementerades när en funktion i WPF-egenskapssystemet krävdes. Funktionerna omfattar databindning, formatering, animering, stöd för standardvärde, arv, bifogade egenskaper och ogiltighet.

Lär dig mer om beroendeegenskaper

  • Komponentutvecklare eller programutvecklare kanske vill skapa en egen beroendeegenskap för att lägga till funktioner, till exempel stöd för databindning eller formatmallar, eller stöd för ogiltighet och värdetvång. Mer information finns i Anpassade beroendeegenskaper.

  • Överväg att beroendeegenskaper är offentliga egenskaper, som kan nås eller identifieras av alla anropare med åtkomst till en instans. Mer information finns i Dependency Property Security.

  • En bifogad egenskap är en typ av egenskap som stöder en specialiserad syntax i XAML. En bifogad egenskap har ofta ingen 1:1-korrespondens med en Common Language Runtime-egenskap och är inte nödvändigtvis en beroendeegenskap. Huvudsyftet med en bifogad egenskap är att tillåta underordnade element att rapportera egenskapsvärden till ett överordnat element, även om det överordnade elementet och det underordnade elementet inte inkluderar den egenskapen som en del av listan med klassmedlemmar. Ett primärt scenario är att aktivera ett underordnat element för att informera överordnade element om hur de ska presenteras i användargränssnittet. Exempel finns i Dock och Left. Mer information finns i översikten över Bifogade egenskaper.

Se även