Delen via


Overzicht van afhankelijkheidseigenschappen

Windows Presentation Foundation (WPF) biedt een set services die kunnen worden gebruikt om de functionaliteit van de eigenschap van een type uit te breiden. Gezamenlijk worden deze services het WPF-eigenschappensysteem genoemd. Een eigenschap die wordt ondersteund door het WPF-eigenschappensysteem, wordt een afhankelijkheidseigenschap genoemd. In dit overzicht worden het WPF-eigenschappensysteem en de mogelijkheden van een afhankelijkheidseigenschap beschreven, waaronder het gebruik van bestaande afhankelijkheidseigenschappen in XAML en in code. In dit overzicht worden ook gespecialiseerde aspecten van afhankelijkheidseigenschappen geïntroduceerd, zoals metagegevens van afhankelijkheden en het maken van uw eigen afhankelijkheidseigenschap in een aangepaste klasse.

Vereiste voorwaarden

In dit artikel wordt ervan uitgegaan dat u basiskennis hebt van het .NET-typesysteem en objectgeoriënteerde programmering. Als u de voorbeelden in dit artikel wilt volgen, is het handig om XAML te begrijpen en te weten hoe u WPF-toepassingen schrijft. Zie Zelfstudie: Een nieuwe WPF-app maken met .NET voor meer informatie.

Afhankelijkheidseigenschappen en CLR-eigenschappen

WPF-eigenschappen worden doorgaans weergegeven als standaard . NET-eigenschappen. U kunt deze eigenschappen op basisniveau gebruiken en nooit weten dat ze worden geïmplementeerd als een afhankelijkheidseigenschap. Als u echter bekend bent met sommige of alle functies van het WPF-eigenschappensysteem, kunt u profiteren van deze functies.

Het doel van afhankelijkheidseigenschappen is om een manier te bieden om de waarde van een eigenschap te berekenen op basis van de waarde van andere invoerwaarden, zoals:

  • Systeemeigenschappen, zoals thema's en gebruikersvoorkeur.
  • Just-In-Time-mechanismen voor eigenschapsbepaling, zoals gegevensbinding en animaties/storyboards.
  • Sjablonen voor meerdere gebruik, zoals resources en stijlen.
  • Waarden die bekend zijn door ouder-kindrelaties met andere elementen in de elementenboom.

Een afhankelijkheidseigenschap kan ook het volgende bieden:

  • Zelfstandige validatie.
  • Standaardwaarden.
  • Callbacks die veranderingen in andere eigenschappen monitoren.
  • Een systeem dat eigenschapswaarden kan dwingen op basis van runtime-informatie.

Afgeleide klassen kunnen bepaalde kenmerken van een bestaande eigenschap wijzigen door de metagegevens van een afhankelijkheidseigenschap te overschrijven, in plaats van de werkelijke implementatie van bestaande eigenschappen te overschrijven of nieuwe eigenschappen te maken.

In de SDK-verwijzing kunt u een afhankelijkheidseigenschap identificeren door de aanwezigheid van een sectie Afhankelijkheidseigenschapsgegevens op de beheerde referentiepagina voor die eigenschap. De sectie Informatie over afhankelijkheden bevat een koppeling naar het DependencyProperty id-veld voor die afhankelijkheidseigenschap. Het bevat ook de lijst met metagegevensopties voor die eigenschap, overschrijvingsinformatie per klasse en andere details.

Afhankelijkheidseigenschappen vormen de basis van CLR-eigenschappen

Afhankelijkheidseigenschappen en het eigenschappensysteem van WPF breiden de functionaliteit van eigenschappen uit door een type te bieden dat een eigenschap ondersteunt, als alternatief voor het standaardpatroon van het ondersteunen van een eigenschap met een privéveld. De naam van dit type is DependencyProperty. Het andere belangrijke type dat het WPF-eigenschappensysteem definieert, is DependencyObject, waarmee de basisklasse wordt gedefinieerd die een afhankelijkheidseigenschap kan registreren en bezitten.

Hier volgt een aantal veelgebruikte terminologie:

  • Afhankelijkheidseigenschap, een eigenschap die wordt ondersteund door een DependencyProperty.

  • Identificatie van afhankelijkheidseigenschap, een DependencyProperty exemplaar dat is verkregen als terugkeerwaarde bij het registreren van een afhankelijkheidseigenschap, en daarna opgeslagen als een statisch lid van een klasse. Veel van de API's die communiceren met het WPF-eigenschappensysteem gebruiken de id van de afhankelijkheidseigenschap als parameter.

  • CLR "wrapper", dat de get en set implementaties voor de eigenschap zijn. Deze implementaties bevatten de id van de afhankelijkheidseigenschap door deze in de GetValue en SetValue aanroepen te gebruiken. Op deze manier biedt het WPF-eigenschapssysteem de backing voor de eigenschap.

In het volgende voorbeeld wordt de IsSpinning afhankelijkheidseigenschap gedefinieerd om de relatie van de DependencyProperty id weer te geven aan de eigenschap waarvan de eigenschap wordt teruggezet.

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

De naamgevingsconventie van de eigenschap en het bijbehorende ondersteunende veld DependencyProperty is belangrijk. De naam van het veld is altijd de naam van de eigenschap, waarbij het achtervoegsel Property is toegevoegd. Zie Aangepaste afhankelijkheidseigenschappen voor meer informatie over deze conventie en de redenen hiervoor.

De waarden van eigenschappen instellen

U kunt eigenschappen instellen in code of in XAML.

Eigenschapswaarden instellen in XAML

In het volgende XAML-voorbeeld wordt de achtergrondkleur van een knop ingesteld op rood. De tekenreekswaarde voor het XAML-kenmerk wordt door de WPF XAML-parser in een WPF-type geconverteerd. In de gegenereerde code is het WPF-type een Color, met behulp van een SolidColorBrush.

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

XAML ondersteunt verschillende syntaxisformulieren voor het instellen van eigenschappen. Welke syntaxis voor een bepaalde eigenschap moet worden gebruikt, is afhankelijk van het waardetype dat een eigenschap gebruikt en andere factoren, zoals de aanwezigheid van een typeconversieprogramma. Zie XAML in WPF- en XAML-syntaxis in detail voor meer informatie over de XAML-syntaxis voor het instellen van eigenschappen

In het volgende XAML-voorbeeld ziet u een andere knopachtergrond die de syntaxis van het eigenschapselement gebruikt in plaats van de kenmerksyntaxis. In plaats van een eenvoudige effen kleur in te stellen, stelt de XAML de knopeigenschap Background in op een afbeelding. Een element vertegenwoordigt die afbeelding en een kenmerk van het geneste element geeft de bron van de afbeelding aan.

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

Eigenschappen instellen in code

Het instellen van afhankelijkheidseigenschapswaarden in code is doorgaans slechts een aanroep van de set implementatie die wordt weergegeven door de CLR 'wrapper':

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

Het ophalen van een eigenschapswaarde is in feite een aanroep van de implementatie van de get wrapper:

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

U kunt ook de API's GetValue van het eigenschappensysteem aanroepen en SetValue rechtstreeks. Het rechtstreeks aanroepen van de API's is geschikt voor sommige scenario's, maar meestal niet wanneer u bestaande eigenschappen gebruikt. Wrappers zijn doorgaans handiger en bieden een betere zichtbaarheid van de eigenschap voor ontwikkelhulpmiddelen.

Eigenschappen kunnen ook worden ingesteld in XAML en later via code-behind in code worden geopend. Zie Code-behind en XAML in WPF voor meer informatie

Eigenschapsfunctionaliteit van een afhankelijkheidseigenschap

In tegenstelling tot een eigenschap die wordt ondersteund door een veld, breidt een afhankelijkheidseigenschap de functionaliteit van een eigenschap uit. De toegevoegde functionaliteit vertegenwoordigt of ondersteunt vaak een van deze functies:

Hulpmiddelen

U kunt een afhankelijkheidseigenschapswaarde instellen door te verwijzen naar een resource. Resources worden doorgaans opgegeven als de Resources eigenschapswaarde van een paginahoofdelement of van de toepassing, omdat deze locaties handige toegang bieden tot de resource. In dit voorbeeld definiëren we een SolidColorBrush resource:

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

Nu de resource is gedefinieerd, kunnen we verwijzen naar de resource om een waarde voor de Background eigenschap op te geven:

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

In WPF XAML kunt u een statische of dynamische resourcereferentie gebruiken. Naar deze specifieke resource wordt verwezen als een DynamicResource

Opmerking

Resources worden behandeld als een lokale waarde, wat betekent dat als u een andere lokale waarde instelt, u de resourcereferentie verwijdert. Zie Prioriteit van eigenschapswaarde voor afhankelijkheden voor meer informatie.

Gegevensbinding

Een afhankelijkheidseigenschap kan verwijzen naar een waarde via gegevensbinding. Gegevensbinding werkt via een specifieke syntaxis van de markup-extensie in XAML of het Binding object in code. Met gegevensbinding wordt de bepaling van de uiteindelijke eigenschapswaarde uitgesteld tot de uitvoeringstijd, waarna de waarde wordt verkregen uit een gegevensbron.

In het volgende voorbeeld wordt de Content eigenschap voor een Button, met behulp van een binding die is gedeclareerd in XAML, ingesteld. De binding maakt gebruik van een overgenomen gegevenscontext en een XmlDataProvider gegevensbron (niet weergegeven). De binding zelf specificeert de broneigenschap binnen de gegevensbron door XPath.

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

Opmerking

Bindingen worden behandeld als een lokale waarde, wat betekent dat als u een andere lokale waarde instelt, u de binding verwijdert. Zie Prioriteit van eigenschapswaarde voor afhankelijkheden voor meer informatie.

Afhankelijkheidseigenschappen, of de DependencyObject klasse, bieden geen systeemeigen ondersteuning INotifyPropertyChanged voor meldingen van wijzigingen in DependencyObject de waarde van de broneigenschap voor bewerkingen voor gegevensbinding. Zie het overzicht van gegevensbindingen voor meer informatie over het maken van eigenschappen voor gebruik in gegevensbindingen die wijzigingen in een gegevensbindingsdoel kunnen rapporteren

Stijlen

Stijlen en sjablonen zijn aantrekkelijke redenen om afhankelijkheidseigenschappen te gebruiken. Stijlen zijn met name handig voor het instellen van eigenschappen die de gebruikersinterface van de toepassing definiëren. Stijlen worden doorgaans gedefinieerd als resources in XAML. Stijlen communiceren met het eigenschappensysteem, omdat ze meestal 'setters' bevatten voor bepaalde eigenschappen en 'triggers' die een eigenschapswaarde wijzigen op basis van de runtime-waarde voor een andere eigenschap.

In het volgende voorbeeld wordt een eenvoudige stijl gemaakt, die in een Resources woordenlijst zou worden gedefinieerd (niet weergegeven). Vervolgens wordt die stijl rechtstreeks toegepast op de Style eigenschap voor een Button. Met de setter binnen de stijl wordt de eigenschap Background voor een gestylede Button ingesteld op groen.

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

Zie Styling en sjabloneren voor meer informatie.

Animaties

Afhankelijkheidseigenschappen kunnen worden geanimeerd. Wanneer een toegepaste animatie wordt uitgevoerd, heeft de waarde met animatie een hogere prioriteit dan een andere eigenschapswaarde, inclusief een lokale waarde.

In het volgende voorbeeld wordt de Background-eigenschap van een Button geanimeerd. Technisch gezien stelt de syntaxis van het eigenschapselement een lege SolidColorBrush waarde in als Backgroundde , en de eigenschap van de ColorSolidColorBrush eigenschap is geanimeerd.

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

Zie Animatieoverzicht en Overzicht van Storyboards voor meer informatie over animatie-eigenschappen

Onderdrukkingen van metagegevens

U kunt specifiek gedrag van een afhankelijkheidseigenschap wijzigen door de metagegevens ervan te overschrijven wanneer u afgeleid bent van de klasse die oorspronkelijk de afhankelijkheidseigenschap heeft geregistreerd. Het overschrijven van metagegevens is afhankelijk van de DependencyProperty id en hoeft de eigenschap niet opnieuw te worden geïmplementeerd. De wijziging van de metagegevens wordt systeemeigen verwerkt door het eigenschappensysteem. Elke klasse bevat mogelijk afzonderlijke metagegevens voor alle eigenschappen die zijn overgenomen van basisklassen, per type.

In het volgende voorbeeld worden metagegevens voor een DefaultStyleKey afhankelijkheidseigenschap overschreven. Het overschrijven van metagegevens voor deze specifieke afhankelijkheidseigenschap maakt deel uit van een implementatiepatroon voor het maken van besturingselementen die standaardstijlen van thema's kunnen gebruiken.

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

Zie voor meer informatie over het overschrijven of openen van metagegevens voor afhankelijkheidseigenschappen, Metagegevens overschrijven voor een afhankelijkheidseigenschap.

Overname van eigenschapswaarde

Een element kan de waarde van een afhankelijkheidseigenschap overnemen van het bovenliggende element in de objectstructuur.

Opmerking

Overnamegedrag van eigenschapswaarden is niet globaal ingeschakeld voor alle afhankelijkheidseigenschappen, omdat de berekeningstijd voor overname van invloed is op de prestaties. Overname van eigenschapswaarden wordt doorgaans alleen ingeschakeld in scenario's die toepasbaarheid voorstellen. U kunt controleren of een afhankelijkheidseigenschap wordt overgenomen door te kijken naar de sectie Informatie over afhankelijkheden voor die afhankelijkheidseigenschap in de SDK-verwijzing.

In het volgende voorbeeld ziet u een binding die de DataContext eigenschap bevat om de bron van de binding op te geven. Bindingen in onderliggende objecten hoeven dus niet de bron op te geven en kunnen de overgenomen waarde van DataContext in het bovenliggende StackPanel-object gebruiken. Een kindobject kan ook rechtstreeks zijn eigen DataContext of een Source opgeven in de Binding, en niet de geërfde waarde gebruiken.

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

Zie overname van eigenschapswaardenvoor meer informatie.

WPF Designer-integratie

Aangepaste besturingselementen met eigenschappen die als afhankelijkheidseigenschappen zijn geïmplementeerd, kunnen goed worden geïntegreerd met WPF Designer voor Visual Studio. Een voorbeeld is de mogelijkheid om eigenschappen van directe en gekoppelde afhankelijkheden te bewerken in het venster Eigenschappen . Zie Het overzicht van het ontwerpen van besturingselementen voor meer informatie

Voorrang van eigenschapwaardes bij afhankelijkheid

Alle invoer op basis van eigenschappen in het WPF-eigenschappensysteem kan de waarde van een afhankelijkheidseigenschap instellen. Voorrang van eigenschapswaarde van afhankelijkheden bestaat, zodat de verschillende scenario's voor hoe eigenschappen hun waarden verkrijgen op een voorspelbare manier interacteren.

Opmerking

In de SDK-documentatie wordt soms de term 'lokale waarde' of 'lokaal ingestelde waarde' gebruikt bij het bespreken van afhankelijkheidseigenschappen. Een lokaal ingestelde waarde is een eigenschapswaarde die rechtstreeks wordt ingesteld op een objectinstantie in code of als elementkenmerk in XAML.

Het volgende voorbeeld bevat een stijl die van toepassing is op de Background eigenschap van elke knop, maar specificeert een knop met een lokaal ingestelde Background eigenschap. Technisch gezien is Background de eigenschap van die knop twee keer ingesteld, hoewel slechts één waarde van toepassing is: de waarde met de hoogste prioriteit. Een lokaal ingestelde waarde heeft de hoogste prioriteit, met uitzondering van een actieve animatie, die hier niet bestaat. De tweede knop gebruikt dus de lokaal ingestelde waarde voor de Background eigenschap in plaats van de waarde van de stijlsetter. De eerste knop heeft geen lokale waarde of een andere waarde met een hogere prioriteit dan een stijlsetter, en gebruikt dus de waarde van de stijlsetter voor de Background eigenschap.

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

Waarom bestaat de prioriteit van de afhankelijkheidseigenschap?

Lokaal ingestelde waarden hebben voorrang op stijlsetwaarden, die lokaal beheer van elementeigenschappen ondersteunen. Zie Prioriteit van eigenschapswaarde voor afhankelijkheden voor meer informatie.

Opmerking

Een aantal eigenschappen die zijn gedefinieerd op WPF-elementen zijn geen afhankelijkheidseigenschappen, omdat afhankelijkheidseigenschappen doorgaans alleen zijn geïmplementeerd wanneer een functie van het WPF-eigenschappensysteem vereist was. De functies omvatten gegevensbinding, stijl, animatie, standaardwaardeondersteuning, overname, gekoppelde eigenschappen en ongeldigheid.

Meer informatie over afhankelijkheidseigenschappen

  • Onderdeelontwikkelaars of toepassingsontwikkelaars willen mogelijk hun eigen afhankelijkheidseigenschap maken om mogelijkheden toe te voegen, zoals ondersteuning voor gegevensbinding of stijlen, of ondersteuning voor ongeldigheid en waardeverkrachting. Zie Aangepaste afhankelijkheidseigenschappenvoor meer informatie.

  • Overweeg afhankelijkheidseigenschappen om openbare eigenschappen te zijn, toegankelijk of detecteerbaar door een beller met toegang tot een exemplaar. Zie Beveiliging van afhankelijkheidseigenschappenvoor meer informatie.

  • Een gekoppelde eigenschap is een type eigenschap dat ondersteuning biedt voor een gespecialiseerde syntaxis in XAML. Een gekoppelde eigenschap heeft vaak geen 1:1-overeenkomst met een common language runtime-eigenschap en is niet noodzakelijkerwijs een dependency property. Het belangrijkste doel van een gekoppelde eigenschap is om kind elementen toe te staan eigenschapswaarden te rapporteren aan een ouder element, zelfs als het ouder element en het kind element die eigenschap niet als onderdeel van hun klasseomschrijvingen hebben. Een primair scenario is het inschakelen van een onderliggend element om bovenliggende elementen te informeren over hoe deze in de gebruikersinterface moeten worden weergegeven. Zie Dock en Left voor voorbeelden. Zie Het overzicht van bijgevoegde eigenschappen voor meer informatie.

Zie ook