Översikt över beroendeegenskaper
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 vanligtvis 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. Detta inkluderar 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
Det här avsnittet förutsätter att du har grundläggande kunskaper om .NET-typsystemet och objektorienterad programmering. För att kunna följa exemplen i det här avsnittet bör du också förstå XAML och veta hur du skriver WPF-program. Mer information finns i Genomgång: Mitt första WPF-skrivbordsprogram.
Beroendeegenskaper och CLR-egenskaper
I WPF exponeras vanligtvis egenskaper som standardegenskaper för .NET . På en grundläggande nivå kan du interagera med dessa egenskaper direkt och aldrig veta att de implementeras som en beroendeegenskap. Du bör dock bekanta dig med vissa eller alla funktioner i WPF-egenskapssystemet, så att du kan 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. Dessa andra indata kan omfatta systemegenskaper som 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 eller värden som är kända via överordnade och underordnade relationer med andra element i elementträdet. Dessutom kan en beroendeegenskap implementeras för att tillhandahålla fristående validering, standardvärden, återanrop som övervakar ändringar i andra egenskaper och ett system som kan tvinga fram egenskapsvärden baserat på potentiell körningsinformation. Härledda klasser kan också ändra vissa specifika egenskaper för en befintlig egenskap genom att åsidosätta metadata för 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 vilken egenskap som är en beroendeegenskap genom att det finns avsnittet Beroendeegenskapsinformation på den hanterade referenssidan för den egenskapen. Avsnittet Information om beroendeegenskap innehåller en länk till fältet DependencyProperty identifierare för den beroendeegenskapen och innehåller även en lista över metadataalternativen som har angetts för den egenskapen, åsidosättningsinformation per klass och annan information.
Beroendeegenskaper stöder CLR-egenskaper
Beroendeegenskaper och WPF-egenskapssystemet utökar egenskapsfunktionaliteten genom att tillhandahålla en typ som används för att understödja en egenskap, som ett alternativ till standardmönstret där egenskapen stöds av ett privat fält. Namnet på den här typen är DependencyProperty. Den andra viktiga typen som definierar WPF-egenskapssystemet är DependencyObject. DependencyObject definierar basklassen som kan registrera och äga en beroendeegenskap.
Följande visar den terminologi som används med beroendeegenskaper:
Dependency-egenskap: En egenskap som stöds av en DependencyProperty.
Beroendeegenskapsidentifierare: En DependencyProperty-instans som hämtas som ett returvärde när du registrerar en beroendeegenskap och sedan lagras som en statisk medlem i en klass. Den här identifieraren används som en parameter för många av de API:er som interagerar med WPF-egenskapssystemet.
CLR "wrapper": Den faktiska get- och set-implementeringen för egenskapen. Dessa implementeringar innehåller beroendeegenskapsidentifieraren genom att använda den i anropen GetValue och SetValue, vilket ger stöd för egenskapen med hjälp av WPF-egenskapssystemet.
I följande exempel definieras IsSpinning
beroendeegenskap och relationen mellan identifieraren DependencyProperty och egenskapen den stödjer.
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
"IsSpinning", typeof(Boolean),
typeof(MyCode)
);
public bool IsSpinning
{
get { return (bool)GetValue(IsSpinningProperty); }
set { SetValue(IsSpinningProperty, value); }
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
DependencyProperty.Register("IsSpinning",
GetType(Boolean),
GetType(MyCode))
Public Property IsSpinning() As Boolean
Get
Return CBool(GetValue(IsSpinningProperty))
End Get
Set(ByVal value As Boolean)
SetValue(IsSpinningProperty, value)
End Set
End Property
Namngivningskonventionen för egenskapen och dess stödfält DependencyProperty är viktiga. 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 som röd. Det här exemplet illustrerar ett fall där det enkla strängvärdet för ett XAML-attribut typkonverteras av WPF XAML-parsern till en WPF-typ (en Color, via en SolidColorBrush) i den genererade koden.
<Button Background="Red" Content="Button!"/>
XAML stöder en mängd olika 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, samt andra faktorer som förekomsten av en typkonverterare. Mer information om XAML-syntax för egenskapsinställning finns i XAML i WPF och XAML-syntax i detalj.
Som ett exempel på icke-attributsyntax visar följande XAML-exempel en annan knappbakgrund. Den här gången i stället för att ange en enkel solid färg, är bakgrunden inställd på en bild, med ett element som representerar bilden och källan till den bilden som anges som ett attribut för det kapslade elementet. Det här är ett exempel på syntax för egenskapselement.
<Button Content="Button!">
<Button.Background>
<ImageBrush ImageSource="wavy.jpg"/>
</Button.Background>
</Button>
Ange egenskaper i kod
Att ange värden för beroendeegenskap i kod är vanligtvis bara ett anrop till den uppsättningsimplementering som tillhandahålls av CLR-omslutaren.
Button myButton = new Button();
myButton.Width = 200.0;
Dim myButton As New Button()
myButton.Width = 200.0
Att hämta ett egenskapsvärde är i grund och botten också ett anrop till get-implementeringen "wrapper".
double whatWidth;
whatWidth = myButton.Width;
Dim whatWidth As Double
whatWidth = myButton.Width
Du kan också anropa egenskapssystemets API:er GetValue och SetValue direkt. Detta är vanligtvis inte nödvändigt om du använder befintliga egenskaper (omslutningarna är mer praktiska och ger bättre exponering av egenskapen för utvecklarverktyg), men att anropa API:erna direkt är lämpligt för vissa scenarier.
Egenskaper kan också anges i XAML och sedan nås senare i kod, via bakomliggande kod. Mer information finns i Code-Behind och XAML i WPF.
Funktioner tillhandahållna av ett beroende attribut
En beroendeegenskap ger funktioner som utökar funktionen för en egenskap i stället för en egenskap som backas upp av ett fält. Sådana funktioner representerar eller stöder ofta någon av följande specifika funktioner:
arv egenskapsvärde
Resurser
Ett beroendeegenskapsvärde kan anges genom att referera till en resurs. Resurser anges vanligtvis som Resources
egenskapsvärde för ett sidrotelement eller för programmet (dessa platser ger den mest praktiska åtkomsten till resursen). I följande exempel visas hur du definierar en SolidColorBrush resurs.
<DockPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</DockPanel.Resources>
När resursen har definierats kan du referera till resursen och använda den för att ange ett egenskapsvärde:
<Button Background="{DynamicResource MyBrush}" Content="I am gold" />
Den här resursen refereras som ett DynamicResource Markup-tillägg (i WPF XAML kan du använda antingen en statisk eller dynamisk resursreferens). Om du vill använda en dynamisk resursreferens måste du 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. Mer information finns i Dependency Property Value Precedence.
Databindning
En beroendeegenskap kan referera till ett värde via databindning. Databindning fungerar genom en specifik markup extension-syntax i XAML, eller Binding-objektet i koden. Med databindning skjuts den slutliga egenskapsvärdebestämningen 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 deklareras i XAML. Bindningen använder en ärvd datakontext och en XmlDataProvider datakälla (visas inte). Själva bindningen anger den önskade källegenskapen med XPath i datasamlingen.
<Button Content="{Binding XPath=Team/@TeamName}"/>
Notera
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 Dependency Property Value Precedence.
Beroendeegenskaper, eller klassen DependencyObject, stöder inte internt INotifyPropertyChanged för att skapa 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
Formatmallar och mallar är två av de främsta motiverande scenarierna för att använda beroendeegenskaper. Format är särskilt användbara för att ange egenskaper som definierar användargränssnittet (UI). Formatmallar definieras vanligtvis som resurser i XAML. Formatmallar interagerar med egenskapssystemet eftersom de vanligtvis innehåller sätta för vissa egenskaper, samt utlösare som ändrar ett egenskapsvärde baserat på det aktuella värdet för en annan egenskap.
I följande exempel skapas ett enkelt format (som skulle definieras i en Resources-ordlista som inte visas) och formatet tillämpas sedan direkt på egenskapen Style för en Button. Settern inom stilen anger egenskapen Background för en stylad Button till grön.
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>
Mer information finns i Styling och templating.
Animationer
Beroendeegenskaper kan animeeras. När en animering tillämpas och körs fungerar det animerade värdet med högre prioritet än något värde (till exempel ett lokalt värde) som egenskapen annars har.
I följande exempel animeras Background på en Button-egenskap (tekniskt sett animeras Background med hjälp av egenskapselementsyntax för att ange en tom SolidColorBrush som Background, och sedan är egenskapen Color i den SolidColorBrush egenskapen som är direkt animerad).
<Button>I am animated
<Button.Background>
<SolidColorBrush x:Name="AnimBrush"/>
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimBrush"
Storyboard.TargetProperty="(SolidColorBrush.Color)"
From="Red" To="Green" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
För ytterligare information om hur du animerar egenskaper, se Animeringsöversikt och Storyboardsöversikt.
Åsidosättningar av metadata
Du kan ändra vissa beteenden för en beroendeegenskap genom att åsidosätta metadata för den egenskapen när du härleder från klassen som ursprungligen registrerar beroendeegenskapen. Åsidosättande metadata förlitar sig på DependencyProperty identifierare. Åsidosättande metadata kräver inte omimplementering av egenskapen. Metadataändringen hanteras internt av egenskapssystemet. varje klass innehåller potentiellt enskilda metadata för alla egenskaper som ärvs från basklasser per typ.
I följande exempel åsidosätts metadata för en beroendeegenskap DefaultStyleKey. Att åsidosätta denna specifika beroendeegenskapsmetadata är en del av ett implementeringsmönster som skapar 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 hur du åsidosätter eller hämtar egenskapsmetadata finns i Metadata för beroendeegenskaper.
Arv av egenskapsvärde
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 har viss prestandapåverkan. Arv av egenskapsvärde är vanligtvis endast aktiverat för egenskaper där ett visst scenario tyder på att arv av egenskapsvärde är lämpligt. Du kan avgöra om en beroendeegenskap ärver genom att titta på avsnittet Dependency Property Information för den beroendeegenskapen i SDK-referensen.
Följande exempel visar en bindning och anger egenskapen DataContext som anger källan för bindningen, som inte visades i det tidigare bindningsexemplet. Eventuella efterföljande bindningar i underordnade objekt behöver inte ange källan. De kan använda det ärvda värdet från DataContext i det överordnade StackPanel objektet. (Alternativt kan ett barnobjekt i stället välja att direkt specificera sitt eget DataContext eller en Source i Binding, och medvetet välja att inte använda det ärvda värdet för bindningarnas datakontext.)
<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource XmlTeamsSource}}">
<Button Content="{Binding XPath=Team/@TeamName}"/>
</StackPanel>
Mer information finns i Arv av egenskapsvärde.
WPF-designerintegrering
En anpassad kontroll med egenskaper som implementeras som beroendeegenskaper får lämpligt stöd i WPF Designer för Visual Studio. Ett exempel är möjligheten att redigera direkta och anslutna beroendeegenskaper med fönstret Egenskaper. Mer information finns i Översikt över kontrollskapande.
Prioritet för beroendeegenskapsvärde
När du får värdet för en beroendeegenskap får du eventuellt ett värde som har angetts för den egenskapen via någon av de andra egenskapsbaserade indata som ingår i WPF-egenskapssystemet. Prioriteten för beroendeegenskapsvärden finns så att en mängd olika scenarier för hur egenskaper hämtar sina värden kan interagera på ett förutsägbart sätt.
Tänk dig följande exempel. Exemplet innehåller ett format som gäller för alla knappar och deras Background egenskaper, men som sedan också anger en knapp med ett lokalt inställt Background värde.
Anteckning
SDK-dokumentationen använder termerna "lokalt värde" eller "lokalt angivet värde" ibland 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 attribut för ett element i XAML.
För den första knappen anges egenskapen i princip två gånger, men endast ett värde gäller: värdet med högsta prioritet. Ett lokalt inställt värde har den högsta prioriteten (förutom en animering som körs, men ingen animering gäller i det här exemplet) och därför används det lokalt inställda värdet i stället för formatuppsättningsvärdet för bakgrunden på den första knappen. Den andra knappen har inget lokalt värde (och inget annat värde med högre prioritet än en formatuppsättning) och därför kommer bakgrunden i den knappen från formatsättaren.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
</Style>
</StackPanel.Resources>
<Button Background="Green">I am NOT red!</Button>
<Button>I am styled red</Button>
</StackPanel>
Varför finns det prioritet för beroendeegenskap?
Normalt skulle du inte vilja att formatmallar alltid ska tillämpas och dölja även ett lokalt angivet värde för ett enskilt element (annars skulle det vara svårt att använda antingen format eller element i allmänhet). Därför har de värden som kommer från formatmallar lägre prioritet än ett lokalt angivet värde. En mer detaljerad lista över beroendeegenskaper och var ett gällande värde för beroendeegenskap kan komma från finns i Dependency Property Value Precedence.
Anteckning
Det finns ett antal egenskaper som definierats för WPF-element som inte är beroendeegenskaper. I stort implementerades egenskaper som beroendeegenskaper endast när det fanns behov av att stödja minst ett av scenarierna som aktiverades av egenskapssystemet: databindning, formatering, animering, standardvärdestöd, arv, bifogade egenskaper eller ogiltighet.
Lär dig mer om beroendeegenskaper
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 CLR-egenskap (Common Language Runtime) och är inte nödvändigtvis en beroendeegenskap. Det typiska syftet 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 båda har den egenskapen som en del av listan över klassmedlemmar. Ett primärt scenario är att göra det möjligt för underordnade element att informera den överordnade om hur de ska visas i användargränssnittet. Ett exempel finns i Dock eller Left. För mer information, se Översikten över bifogade egenskaper .
Komponentutvecklare eller programutvecklare kanske vill skapa en egen beroendeegenskap för att aktivera funktioner som stöd för databindning eller formatmallar, eller för stöd för ogiltighet och värdetvång. Mer information finns i anpassade beroendeegenskaper.
Överväg att beroendeegenskaper är offentliga egenskaper, som är tillgängliga eller åtminstone kan identifieras av en anropare som har åtkomst till en instans. Mer information finns i Dependency Property Security.
Se även
.NET Desktop feedback