Delen via


Prioriteit van eigenschapswaarde van afhankelijkheid

In dit onderwerp wordt uitgelegd hoe de werking van het WPF-eigenschappensysteem (Windows Presentation Foundation) van invloed kan zijn op de waarde van een afhankelijkheidseigenschap en beschrijft de prioriteit waarmee aspecten van het eigenschapssysteem van toepassing zijn op de effectieve waarde van een eigenschap.

Voorwaarden

In dit onderwerp wordt ervan uitgegaan dat u afhankelijkheidseigenschappen begrijpt vanuit het perspectief van een consument van bestaande afhankelijkheidseigenschappen in WPF-klassen en Overzicht van eigenschappen van afhankelijkheden hebt gelezen. Als u de voorbeelden in dit onderwerp wilt volgen, moet u ook XAML begrijpen en weten hoe u WPF-toepassingen schrijft.

Het WPF-eigenschappensysteem

Het WPF-eigenschappensysteem biedt een krachtige manier om de waarde van afhankelijkheidseigenschappen te laten bepalen door verschillende factoren, waardoor functies zoals realtime eigenschapsvalidatie, late binding en het melden van gerelateerde eigenschappen van wijzigingen in waarden voor andere eigenschappen worden ingeschakeld. De exacte volgorde en logica die wordt gebruikt om waarden voor afhankelijkheden te bepalen, is redelijk complex. Als u deze volgorde kent, kunt u onnodige instelling van eigenschappen voorkomen en kan het ook helpen om verwarring op te helderen over waarom bepaalde pogingen om de waarde van een afhankelijkheidseigenschap te beïnvloeden of aan te passen niet de verwachte resultaten opleverden.

Afhankelijkheidseigenschappen kunnen op meerdere locaties worden ingesteld

Hier volgt een voorbeeld van XAML waarbij dezelfde eigenschap (Background) drie verschillende 'set'-bewerkingen heeft die van invloed kunnen zijn op de waarde.

<StackPanel>
    <StackPanel.Resources>
        <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
            <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" 
                    BorderBrush="{TemplateBinding BorderBrush}">
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
            </Border>
        </ControlTemplate>
    </StackPanel.Resources>

    <Button Template="{StaticResource ButtonTemplate}" Background="Red">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Blue"/>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="Yellow" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
        Which color do you expect?
    </Button>
</StackPanel>

Welke kleur verwacht u hier: rood, groen of blauw?

Met uitzondering van geanimeerde waarden en dwang worden lokale eigenschappensets ingesteld op de hoogste prioriteit. Als u een waarde lokaal instelt, kunt u verwachten dat de waarde wordt gehonoreerd, zelfs boven eventuele stijlen of besturingssjablonen. Hier in het voorbeeld is Background lokaal ingesteld op Rood. Daarom is de stijl die in dit bereik is gedefinieerd, ook al is het een impliciete stijl die anders van toepassing is op alle elementen van dat type in dat bereik, niet de hoogste prioriteit voor het geven van de eigenschap Background de waarde ervan. Als u de lokale waarde van Rood uit dat knop-exemplaar hebt verwijderd, zou de stijl voorrang hebben, en zou de knop de achtergrondwaarde uit de stijl krijgen. Triggers hebben in de stijl voorrang, dus de knop zal blauw worden als de muis erop staat, en anders groen.

Prioriteitslijst voor afhankelijkheidseigenschappen instellen

Hier volgt de definitieve volgorde die het eigenschappensysteem gebruikt bij het toewijzen van de runtimewaarden van afhankelijkheidseigenschappen. De hoogste prioriteit wordt als eerste weergegeven. Deze lijst breidt enkele van de generalisaties uit die zijn gemaakt in het overzicht van afhankelijkheidseigenschappen.

  1. Eigenschapssysteem dwang. Zie Coercion, Animation en Base Value verderop in dit onderwerp voor meer informatie over dwang.

  2. Actieve animaties of animaties met een 'Hold'-gedrag. Als u een praktisch effect wilt hebben, moet een animatie van een eigenschap voorrang hebben op de basiswaarde (niet-geanimeerd), zelfs als die waarde lokaal is ingesteld. Zie Coercion, Animation en Base Value verderop in dit onderwerp voor meer informatie.

  3. Lokale waarde. Een lokale waarde kan worden ingesteld via het gemak van de eigenschap 'wrapper', die ook gelijk is aan instellen als een kenmerk of eigenschapselement in XAML, of door een aanroep naar de SetValue-API met behulp van een eigenschap van een specifiek exemplaar. Als u een lokale waarde instelt met behulp van een binding of een resource, handelen deze beide in de prioriteit alsof er een directe waarde is ingesteld.

  4. Eigenschappen van het TemplatedParent-sjabloon. Een element heeft een TemplatedParent als het is gemaakt als onderdeel van een sjabloon (een ControlTemplate of DataTemplate). Zie TemplatedParent verderop in dit onderwerp voor meer informatie over wanneer dit van toepassing is. Binnen de sjabloon is de volgende prioriteit van toepassing:

    1. Triggers uit de TemplatedParent-sjabloon.

    2. Eigenschapsets (meestal via XAML-attributen) in de TemplatedParent-sjabloon.

  5. Impliciete stijl. Is alleen van toepassing op de eigenschap Style. De eigenschap Style wordt gevuld door een stijlresource met een sleutel die overeenkomt met het type van dat element. Deze stijlresource moet bestaan op de pagina of in de toepassing; Zoeken naar een impliciete stijlresource gaat niet verder met de thema's.

  6. Stijltriggers. De triggers binnen stijlen van pagina of toepassing (deze stijlen zijn mogelijk expliciete of impliciete stijlen, maar niet van de standaardstijlen, die een lagere prioriteit hebben).

  7. Sjabloontriggers. Een trigger van een sjabloon binnen een stijl of een rechtstreeks toegepaste sjabloon.

  8. Trendsetters in stijl. Waarden uit een Setter binnen de stijlen van een pagina of applicatie.

  9. Standaardstijl (thema). Zie Standaardstijlen (thema) verderop in dit onderwerp voor meer informatie over wanneer dit van toepassing is en hoe themastijlen betrekking hebben op de sjablonen in themastijlen. Binnen een standaardstijl is de volgende volgorde van prioriteit van toepassing:

    1. Actieve triggers in de themastijl.

    2. Setters in de themastijl.

  10. Erfenis. Een paar afhankelijkheidseigenschappen nemen hun waarden over van bovenliggend element naar onderliggende elementen, zodat ze niet specifiek hoeven te worden ingesteld voor elk element in een toepassing. Zie overname van eigenschapswaardenvoor meer informatie.

  11. Standaardwaarde van metagegevens van afhankelijkheidseigenschappen. Elke afhankelijkheidseigenschap kan een standaardwaarde hebben die is ingesteld door de registratie van het eigenschappensysteem van die specifieke eigenschap. Afgeleide klassen die een afhankelijkheidseigenschap overnemen, hebben ook de mogelijkheid om die metagegevens (inclusief de standaardwaarde) per type te overschrijven. Zie metagegevens van eigenschappen van afhankelijkheden voor meer informatie. Omdat overervingsregels worden gecontroleerd vóór de standaardwaarde, heeft bij een overgenomen eigenschap de standaardwaarde van een bovenliggend element voorrang boven die van een onderliggend element. Dus als een overgenomen eigenschap nergens is ingesteld, wordt de standaardwaarde zoals opgegeven bij de root of het bovenliggende element gebruikt in plaats van de standaardwaarde van het onderliggende element.

TemplatedParent

TemplatedParent als prioriteitsitem is niet van toepassing op een eigenschap van een element dat u rechtstreeks declareert in standaardtoepassingsmarkeringen. Het concept TemplatedParent bestaat alleen voor elementen die kinderen zijn binnen een visuele boom die ontstaan door de toepassing van de sjabloon. Wanneer het eigenschappensysteem de TemplatedParent-sjabloon zoekt naar een waarde, wordt gezocht naar de sjabloon die dat element heeft gemaakt. De eigenschapswaarden van de TemplatedParent-sjabloon fungeren over het algemeen alsof ze zijn ingesteld als een lokale waarde op het onderliggende element, maar deze lagere prioriteit ten opzichte van de lokale waarde bestaat omdat de sjablonen mogelijk worden gedeeld. Zie TemplatedParentvoor meer informatie.

De eigenschap Stijl

De volgorde van de eerder beschreven zoekactie is van toepassing op alle mogelijke afhankelijkheidseigenschappen, behalve op één: de eigenschap Style. De eigenschap Style is uniek omdat deze niet zelf kan worden gestijld, zodat de prioriteit items 5 tot en met 8 niet van toepassing zijn. Het wordt ook niet aanbevolen om Style te animeren of te forceren (en om Style te animeren is een aangepaste animatieklasse vereist). Dit laat drie manieren achter waarop de eigenschap Style kan worden ingesteld:

  • Expliciete stijl. De eigenschap Style is rechtstreeks ingesteld. In de meeste scenario's wordt de stijl niet inline gedefinieerd, maar in plaats daarvan wordt er naar verwezen als een resource, met expliciete sleutel. In dit geval fungeert de eigenschap Stijl zelf alsof het een lokale waarde is, prioriteitsitem 3.

  • Impliciete stijl. De eigenschap Style is niet rechtstreeks ingesteld. De Style bestaat echter op een bepaald niveau in de opzoekvolgorde van resources (pagina, toepassing) en wordt met behulp van een resourcesleutel die overeenkomt met het type waarop de stijl moet worden toegepast. In dit geval handelt de eigenschap Style zelf door een prioriteit die in de reeks is geïdentificeerd als item 5. Deze voorwaarde kan worden gedetecteerd met behulp van DependencyPropertyHelper voor de eigenschap Style en op zoek naar ImplicitStyleReference in de resultaten.

  • standaardstijl, ook wel themastijl genoemd. De eigenschap Style is niet rechtstreeks ingesteld en wordt in feite gelezen als null tot aan runtime. In dit geval is de stijl afkomstig van de evaluatie van runtimethema's die deel uitmaakt van de WPF-presentatie-engine.

Voor impliciete stijlen die niet in thema's staan, moet het type exact overeenkomen- een MyButtonButton-afgeleide klasse gebruikt geen impliciete stijl voor Button.

Standaard (thema) stijlen

Elk besturingselement dat wordt geleverd met WPF heeft een standaardstijl. Deze standaardstijl varieert mogelijk per thema. Daarom wordt deze standaardstijl ook wel een themastijl genoemd.

De belangrijkste informatie in een standaardstijl voor een controle-element is de controletemplate, die in de themastijl bestaat als een setter voor de eigenschap Template. Als er geen sjabloon uit standaardstijlen bestaat, heeft een besturingselement zonder aangepaste sjabloon als onderdeel van een aangepaste stijl helemaal geen visueel uiterlijk. De sjabloon van de standaardstijl geeft het visuele uiterlijk van elk besturingselement een basisstructuur en definieert ook de verbindingen tussen eigenschappen die zijn gedefinieerd in de visualstructuur van de sjabloon en de bijbehorende besturingselementklasse. Elk besturingselement bevat een set eigenschappen die invloed kunnen hebben op het uiterlijk van het besturingselement zonder de sjabloon volledig te vervangen. Denk bijvoorbeeld aan de standaardweergave van een Thumb bedieningselement, een onderdeel van een ScrollBar.

Een Thumb heeft bepaalde aanpasbare eigenschappen. De standaardsjabloon van een Thumb maakt een basisstructuur/visuele boom met verschillende geneste Border-componenten om een afgeschuinde look te creëren. Als een eigenschap die deel uitmaakt van de sjabloon bedoeld is voor aanpassing door de Thumb-klasse, moet die eigenschap worden weergegeven door een TemplateBinding, binnen de sjabloon. In het geval van Thumbdelen verschillende eigenschappen van deze randen een sjabloonbinding met eigenschappen zoals Background of BorderThickness. Maar bepaalde andere eigenschappen of visuele indelingen zijn vastgelegd in de besturingssjabloon of zijn gebonden aan waarden die rechtstreeks afkomstig zijn van het thema en kunnen niet worden gewijzigd door het vervangen van de hele sjabloon. Als een eigenschap afkomstig is van een bovenliggende sjabloon en niet wordt weergegeven door een sjabloonbinding, kan deze niet worden aangepast door stijlen omdat er geen eenvoudige manier is om deze te richten. Maar deze eigenschap kan nog steeds worden beïnvloed door overname van eigenschapswaarden in de toegepaste sjabloon of standaardwaarde.

De themastijlen gebruiken een type als sleutel in hun definities. Wanneer thema's echter worden toegepast op een bepaald elementexemplaar, wordt het opzoeken van thema's voor dit type uitgevoerd door de eigenschap DefaultStyleKey op een controle te controleren. Dit is in tegenstelling tot het gebruik van het letterlijke type, zoals impliciete stijlen doen. De waarde van DefaultStyleKey zou overnemen naar afgeleide klassen, zelfs als de implementeerfunctie deze niet heeft gewijzigd (de beoogde manier om de eigenschap te wijzigen, is om deze niet te overschrijven op eigenschapsniveau, maar om in plaats daarvan de standaardwaarde in metagegevens van eigenschappen te wijzigen). Met deze indirectie kunnen basisklassen de themastijlen definiëren voor afgeleide elementen die anders geen stijl hebben (of belangrijker, geen sjabloon in die stijl hebben en dus helemaal geen standaardvisual uiterlijk hebben). U kunt dus MyButton afleiden uit Button en de standaardsjabloon Button nog steeds ophalen. Als u de auteur van MyButton was en u een ander gedrag wilde, zou u de metagegevens van de afhankelijkheidseigenschap voor DefaultStyleKey op MyButton kunnen overschrijven om een andere sleutel te retourneren. Vervolgens kunt u de relevante themastijlen definiëren, inclusief de sjabloon voor MyButton, die u moet verpakken met uw MyButton-controle. Raadpleeg Overzicht van auteurschap van besturingselementen voor meer informatie over thema's, stijlen en besturingselementen.

Dynamische bronnen en koppeling

Dynamische bronverwijzingen en bindingsbewerkingen respecteren de prioriteit van de locatie waarop ze zijn ingesteld. Een dynamische resource die wordt toegepast op een lokale waarde fungeert bijvoorbeeld per prioriteitsitem 3, een binding voor een eigenschapssetter binnen een themastijl is van toepassing op prioriteitsitem 9, enzovoort. Omdat dynamische resourceverwijzingen en bindingen beide waarden moeten kunnen verkrijgen uit de uitvoeringstijd van de toepassing, houdt dit in dat het werkelijke proces van het bepalen van de prioriteit van de eigenschapswaarde voor een bepaalde eigenschap ook in de uitvoeringstijd wordt uitgebreid.

Dynamische bronverwijzingen maken niet strikt deel uit van het eigenschappensysteem, maar ze hebben wel een opzoekvolgorde die communiceert met de bovenstaande volgorde. Deze prioriteit wordt grondiger gedocumenteerd in de XAML-resources. De basisoverzicht van die volgorde van belangrijkheid is: element naar paginawortel, toepassing, thema, systeem.

Dynamische resources en bindingen hebben de prioriteit van waar ze zijn ingesteld, maar de waarde wordt uitgesteld. Een gevolg hiervan is dat als u een dynamische resource of binding instelt op een lokale waarde, elke wijziging in de lokale waarde de dynamische resource of binding volledig vervangt. Zelfs als u de ClearValue-methode aanroept om de lokale waarde te wissen, wordt de dynamische bron of koppeling niet hersteld. Als u ClearValue aanroept voor een eigenschap die een dynamische resource of binding bevat (zonder letterlijke lokale waarde), worden ze ook gewist door het aanroepen van ClearValue.

SetCurrentValue

De methode SetCurrentValue is een andere manier om een eigenschap in te stellen, maar deze heeft geen prioriteit. In plaats daarvan kunt u met SetCurrentValue de waarde van een eigenschap wijzigen zonder de bron van een vorige waarde te overschrijven. U kunt SetCurrentValue gebruiken wanneer u een waarde wilt instellen zonder deze waarde de prioriteit van een lokale waarde te geven. Als een eigenschap bijvoorbeeld is ingesteld door een trigger en vervolgens een andere waarde via SetCurrentValueheeft toegewezen, respecteert het eigenschapssysteem nog steeds de trigger en wordt de eigenschap gewijzigd als de actie van de trigger plaatsvindt. SetCurrentValue kunt u de waarde van de eigenschap wijzigen zonder deze een bron met een hogere prioriteit te geven. Op dezelfde manier kunt u SetCurrentValue gebruiken om de waarde van een eigenschap te wijzigen zonder een binding te overschrijven.

Dwang, animaties en basiswaarde

Coercion en animatie werken beide op een waarde die wordt aangeduid als de 'basiswaarde' in deze SDK. De basiswaarde is dus elke waarde die wordt bepaald door opwaartse waarden in de items te evalueren totdat item 2 is bereikt.

Voor een animatie kan de basiswaarde een effect hebben op de waarde van de animatie, als deze animatie niet zowel Van als Aan opgeeft voor bepaald gedrag, of als de animatie opzettelijk wordt teruggezet naar de basiswaarde wanneer deze is voltooid. Om dit in de praktijk te zien, voert u de From, To, and By-animationdoelwaardenvoorbeeld uit. Stel de lokale waarden van de hoogte van de rechthoek in het voorbeeld zo in, dat de initiële lokale waarde verschilt van elke "From" -waarde in de animatie. U zult opmerken dat de animaties direct beginnen met de waarden 'Van' en de basiswaarde vervangen zodra ze zijn gestart. De animatie kan worden gespecificeerd om terug te keren naar de waarde die voor de animatie werd gevonden, door Stop FillBehaviorop te geven zodra deze is voltooid. Daarna wordt de normale prioriteit gebruikt voor de bepaling van de basiswaarde.

Er kunnen meerdere animaties worden toegepast op één eigenschap, waarbij elk van deze animaties mogelijk is gedefinieerd vanuit verschillende punten in de prioriteit van de waarde. Deze animaties zullen echter mogelijk hun waarden samenstellen, in plaats van alleen de animatie met hogere prioriteit toe te passen. Dit is afhankelijk van precies hoe de animaties worden gedefinieerd en het type van de waarde die wordt geanimeerd. Zie Animatieoverzichtvoor meer informatie over animatie-eigenschappen.

Dwang is van toepassing op alle hoogste niveaus. Zelfs een reeds actieve animatie is onderhevig aan waarde-dwang. Bepaalde bestaande afhankelijkheidseigenschappen in WPF hebben ingebouwde dwang. Voor een aangepaste afhankelijkheidseigenschap definieert u het coerciegedrag door een CoerceValueCallback te schrijven en de callback als onderdeel van de metagegevens door te geven wanneer u de eigenschap maakt. U kunt ook dwanggedrag van bestaande eigenschappen veranderen door de metagegevens van die eigenschap in een afgeleide klasse te herschrijven. Coercion communiceert met de basiswaarde op een zodanige manier dat de beperkingen op dwang worden toegepast als deze beperkingen op dat moment bestaan, maar de basiswaarde blijft behouden. Als beperkende factoren bij dwang later worden opgeheven, zal de dwang de dichtstbijzijnde waarde ten opzichte van die basiswaarde teruggeven. Bovendien kan de invloed van de dwang op een eigenschap ophouden zodra alle beperkingen zijn opgeheven. Zie voor meer informatie over dwinggedrag Dependency Property Callbacks en Validatie.

Triggergedragingen

Besturingselementen definiëren vaak triggergedrag als onderdeel van hun standaardstijl in thema's. Het instellen van lokale eigenschappen op besturingselementen voorkomt mogelijk dat de triggers visueel of gedragsmatig kunnen reageren op gebruikersgebeurtenissen. Het meest voorkomende gebruik van een eigenschapstrigger is voor besturings- of statuseigenschappen zoals IsSelected. Als een Button bijvoorbeeld standaard is uitgeschakeld (met falseals trigger voor IsEnabled), dan is de Foreground waarde in de themastijl verantwoordelijk voor het "grijs weergeven" van het besturingselement. Maar als u een lokale Foreground-waarde hebt ingesteld, wordt die normale grijze kleur met voorrang overschreven door uw lokale instellingen, zelfs in dit door eigenschappen geactiveerde scenario. Wees voorzichtig met het instellen van waarden voor eigenschappen met triggergedrag op themaniveau en zorg ervoor dat u de beoogde gebruikerservaring voor dat besturingselement niet onnodig verstoort.

Prioriteit van ClearValue en Waarde

De methode ClearValue biedt een expedient middel om een lokaal toegepaste waarde te wissen van een afhankelijkheidseigenschap die is ingesteld op een element. Het aanroepen van ClearValue is echter geen garantie dat de standaardwaarde zoals vastgelegd in metagegevens tijdens de registratie van eigenschappen de nieuwe effectieve waarde is. Alle andere deelnemers aan waardeprioriteit zijn nog steeds actief. Alleen de lokaal ingestelde waarde is verwijderd uit de volgorde van prioriteit. Als u bijvoorbeeld ClearValue aanroept voor een eigenschap waarin die eigenschap ook wordt ingesteld door een themastijl, wordt de themawaarde toegepast als de nieuwe waarde in plaats van de standaardwaarde op basis van metagegevens. Als u alle deelnemers aan de eigenschapswaarde uit het proces wilt halen en de waarde wilt instellen op de standaardwaarde voor geregistreerde metagegevens, kunt u die standaardwaarde definitief verkrijgen door een query uit te voeren op de metagegevens van de afhankelijkheidseigenschap en vervolgens kunt u de standaardwaarde gebruiken om de eigenschap lokaal in te stellen met een aanroep naar SetValue.

Zie ook