Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De werking van het WPF-eigenschappensysteem (Windows Presentation Foundation) is van invloed op de waarde van een afhankelijkheidseigenschap. In dit artikel wordt uitgelegd hoe de prioriteit van verschillende invoer op basis van eigenschappen binnen het WPF-eigenschappensysteem de effectieve waarde van een afhankelijkheidseigenschap bepaalt.
Vereiste voorwaarden
In het artikel wordt ervan uitgegaan dat u basiskennis hebt van afhankelijkheidseigenschappen en dat u overzicht van eigenschappen van afhankelijkheden hebt gelezen. Als u de voorbeelden in dit artikel wilt volgen, helpt dit als u bekend bent met Extensible Application Markup Language (XAML) en weet hoe u WPF-toepassingen schrijft.
Het WPF-eigenschappensysteem
Het WPF-eigenschappensysteem gebruikt verschillende factoren om de waarde van dependency properties te bepalen, zoals realtime eigenschapsvalidatie, late binding en wijzigingsmeldingen voor gerelateerde eigenschappen. Hoewel de volgorde en logica die wordt gebruikt om waarden voor afhankelijkheden te bepalen complex is, kunt u hiermee onnodige eigenschapsinstellingen voorkomen en ook nagaan waarom een poging om een afhankelijkheidseigenschap in te stellen niet heeft resulteert in de verwachte waarde.
Afhankelijkheidseigenschappen ingesteld op meerdere locaties
In het volgende XAML-voorbeeld ziet u hoe drie verschillende 'set'-bewerkingen op de eigenschap Background van de knop de waarde ervan kunnen beïnvloeden.
<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>
In het voorbeeld is de eigenschap Background lokaal ingesteld op Red. De impliciete stijl die in het bereik van de knop is gedeclareerd, probeert echter de eigenschap Background in te stellen op Blue. En wanneer de muis boven de knop staat, probeert de trigger in de impliciete stijl de eigenschap Background in te stellen op Yellow. Met uitzondering van dwang en animatie heeft een lokaal ingestelde eigenschapswaarde de hoogste prioriteit, dus de knop wordt rood, zelfs bij de muisaanwijzer. Maar als u de lokaal ingestelde waarde van de knop verwijdert, krijgt deze de Background waarde uit de stijl. Binnen een stijl hebben triggers voorrang, dus de knop wordt geel wanneer de muis erboven hangt en anders blauw. In het voorbeeld wordt de standaardwaarde ControlTemplate van de knop vervangen omdat de standaardsjabloon een hard-gecodeerd mouseover-effect met de waarde Background heeft.
Voorrangslijst voor afhankelijkheidseigenschappen
De volgende lijst is de definitieve volgorde van prioriteit die het eigenschappensysteem gebruikt bij het toewijzen van runtimewaarden aan afhankelijkheidseigenschappen. De hoogste prioriteit wordt als eerste weergegeven.
Eigenschapssysteem dwang. Zie Coercion en animatiesvoor meer informatie over coercion.
Actieve animaties of animaties met een vasthoudgedrag. Als u een praktisch effect wilt hebben, moet een animatiewaarde voorrang hebben op de basiswaarde (niet-animatie) zelfs als de basiswaarde lokaal is ingesteld. Zie Coercion en animatiesvoor meer informatie.
Lokale waarden. U kunt een lokale waarde instellen via een 'wrapper'-eigenschap, die gelijk is aan het instellen van een kenmerk of eigenschapselement in XAML, of door een aanroep naar de SetValue-API met behulp van een eigenschap van een specifiek exemplaar. Een lokale waarde die is ingesteld via een binding of resource, heeft dezelfde prioriteit als een waarde die rechtstreeks is ingesteld.
GevormdeOuder sjabloon eigenschapwaarden. Een element heeft een TemplatedParent als het is gemaakt door een sjabloon (ControlTemplate of DataTemplate). Zie TemplatedParentvoor meer informatie. Binnen de sjabloon die is opgegeven door de
TemplatedParent, is de volgorde van prioriteit:Triggers
Eigenschapsets, meestal door middel van XAML-kenmerken.
Impliciete stijlen. Is alleen van toepassing op de eigenschap Style. De
Stylewaarde is een stijlresource met een TargetType waarde die overeenkomt met het elementtype. De stijlresource moet bestaan binnen de pagina of toepassing. Het zoeken naar een impliciete stijlbron wordt niet uitgebreid naar stijlbronnen in thema's.Stijltriggers. Een stijltrigger is een aanjager binnen een expliciete of impliciete stijl. De stijl moet bestaan binnen de pagina of toepassing. Triggers in standaardstijlen hebben een lagere prioriteit.
sjabloon-triggers. Een sjabloontrigger is een trigger van een rechtstreeks toegepaste sjabloon of van een sjabloon in een stijl. De stijl moet bestaan binnen de pagina of toepassing.
stijl-instelwaarden. Een stijlsetwaarde is een waarde die wordt toegepast door een Setter binnen een stijl. De stijl moet bestaan binnen de pagina of toepassing.
standaardstijlen, ook wel themastijlen genoemd. Zie Standaardstijlen (thema)voor meer informatie. Binnen een standaardstijl is de volgorde van prioriteit:
Actieve triggers.
Setters.
Erfenis. Sommige afhankelijkheidseigenschappen van een kindelement nemen hun waarde over van het bovenliggende element. Het is dus mogelijk niet nodig om eigenschapswaarden in te stellen op elk element in de toepassing. Zie overname van eigenschapswaardenvoor meer informatie.
Standaardwaarde uit metagegevens van afhankelijke eigenschappen Een afhankelijkheidseigenschap kan een standaardwaarde hebben ingesteld tijdens de registratie van die eigenschap. Afgeleide klassen die een afhankelijkheidseigenschap overnemen, kunnen metagegevens van afhankelijkheden overschrijven (inclusief de standaardwaarde) per type. Zie metagegevens van eigenschappen van afhankelijkhedenvoor meer informatie. Voor een overgenomen eigenschap heeft de standaardwaarde van een bovenliggend element voorrang op de standaardwaarde van een onderliggend element. Dus als een overgenomen eigenschap niet is ingesteld, wordt de standaardwaarde van de root of het bovenliggende element gebruikt in plaats van de standaardwaarde van het onderliggende element.
TemplatedParent
TemplatedParent prioriteit is niet van toepassing op eigenschappen van elementen die rechtstreeks in standaardtoepassingsmarkeringen worden gedeclareerd. Het TemplatedParent concept bestaat alleen voor onderliggende items in een visuele boomstructuur die ontstaan door de toepassing van een sjabloon. Wanneer het eigenschapssysteem de sjabloon, opgegeven door de TemplatedParent, doorzoekt naar de eigenschapswaarden van een element, zoekt het in de sjabloon die het element heeft voortgebracht. De eigenschapswaarden van de sjabloon TemplatedParent fungeren over het algemeen alsof ze lokaal waarden voor het element zijn ingesteld, maar met minder prioriteit dan werkelijke lokale waarden, omdat sjablonen mogelijk worden gedeeld. Zie TemplatedParent voor meer informatie.
De eigenschap Stijl
Dezelfde volgorde van prioriteit is van toepassing op alle afhankelijkheidseigenschappen, met uitzondering van de eigenschap Style. De eigenschap Style is uniek omdat deze niet zelf kan worden gestijld. Het wordt niet aanbevolen om de eigenschap Style te forceren of te animeren (en het animeren van de eigenschap Style zou een aangepaste animatieklasse vereisen). Als gevolg hiervan zijn niet alle prioriteitsitems van toepassing. Er zijn slechts drie manieren om de eigenschap Style in te stellen:
Expliciete stijl. De eigenschap
Stylevan een element wordt rechtstreeks ingesteld. DeStyleeigenschapswaarde fungeert alsof het een lokale waarde is en dezelfde prioriteit heeft als item 3 in de prioriteitslijst. In de meeste scenario's worden expliciete stijlen niet inline gedefinieerd en worden in plaats daarvan expliciet verwezen als een resource, bijvoorbeeldStyle="{StaticResource myResourceKey}".Impliciete stijl. De eigenschap
Stylevan een element is niet rechtstreeks ingesteld. In plaats daarvan wordt een stijl toegepast wanneer deze op een bepaald niveau binnen de pagina of toepassing bestaat en een resourcesleutel heeft die overeenkomt met het type element waarop de stijl van toepassing is, bijvoorbeeld<Style TargetType="x:Type Button">. Het type moet exact overeenkomen, bijvoorbeeld<Style TargetType="x:Type Button">niet wordt toegepast opMyButtontype, zelfs niet alsMyButtonis afgeleid vanButton. De eigenschapswaardeStyleheeft dezelfde prioriteit als item 5 in de prioriteitslijst. Een impliciete stijlwaarde kan worden gedetecteerd door de methode DependencyPropertyHelper.GetValueSource aan te roepen, de eigenschapStyledoor te geven en te controleren opImplicitStyleReferencein de resultaten.standaardstijl, ook wel themastijlgenoemd. De eigenschap
Stylevan een element is niet rechtstreeks ingesteld. In plaats daarvan is het afkomstig van de evaluatie van runtimethema's door de WPF-presentatie-engine. Voor de uitvoeringstijd is de eigenschapswaardeStylenull. De eigenschapswaardeStyleheeft dezelfde prioriteit als item 9 in de prioriteitslijst.
Standaard (Thema)stijlen
Elk besturingselement dat wordt geleverd met WPF heeft een standaardstijl die per thema kan variëren. Daarom wordt de standaardstijl soms een themastijlgenoemd.
De ControlTemplate is een belangrijk item in de standaardstijl voor een besturingselement.
ControlTemplate is een setterwaarde voor de eigenschap Template van de stijl. Als standaardstijlen geen sjabloon bevatten, heeft een besturingselement zonder een aangepaste sjabloon als onderdeel van een aangepaste stijl geen visueel uiterlijk. Niet alleen definieert een sjabloon het uiterlijk van een besturingselement, maar definieert ook de verbindingen tussen eigenschappen 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 te vervangen. Denk bijvoorbeeld aan de standaard visuele verschijning van een Thumb besturingselement, dat een ScrollBar onderdeel is.
Een Thumb bedieningselement heeft bepaalde aanpasbare eigenschappen. Met de standaardsjabloon van een Thumb controle wordt een basisstructuur of visuele boom gemaakt, met verschillende geneste Border onderdelen om een afgeschuinde uitstraling te creëren. Binnen de sjabloon worden eigenschappen die zijn bedoeld om te worden aangepast door de Thumb klasse weergegeven via TemplateBinding
Standaardstijlen geven een TargetType op in hun definities. Evaluatie van runtimethema's komt overeen met de TargetType van een standaardstijl met de eigenschap DefaultStyleKey van een besturingselement. Het opzoekgedrag voor impliciete stijlen maakt daarentegen gebruik van het daadwerkelijke type van het bedieningselement. De waarde van DefaultStyleKey wordt overgenomen door afgeleide klassen, zodat afgeleide elementen die anders geen gekoppelde stijl hebben, een standaardvisualisatie krijgen. Als u bijvoorbeeld MyButton afgeleid van Button, neemt MyButton de standaardsjabloon van Buttonover. Afgeleide klassen kunnen de standaardwaarde van DefaultStyleKey in metagegevens van afhankelijkheden overschrijven. Dus als u een andere visuele weergave voor MyButtonwilt, kunt u de metagegevens van de afhankelijkheidseigenschap voor DefaultStyleKey op MyButtonoverschrijven en vervolgens de relevante standaardstijl definiëren, inclusief een sjabloon, die u inpakt met uw MyButton besturingselement. Zie Het overzicht van het ontwerpen van besturingselementen voor meer informatie
Dynamische bron
Dynamische bronverwijzingen maken technisch geen deel uit van het eigenschappensysteem en hebben hun eigen opzoekvolgorde die communiceert met de prioriteitslijst. In wezen is de voorrang van dynamische resourceverwijzingen als volgt: van element naar paginawortel, applicatie, thema en vervolgens systeem. Zie XAML-resourcesvoor meer informatie.
Hoewel dynamische resourceverwijzingen en bindingen de prioriteit hebben van de locatie waarop ze zijn ingesteld, wordt de waarde 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 methode ClearValue aanroept om de lokaal gedefinieerde waarde te wissen, wordt de dynamische bron of binding niet hersteld. Als u ClearValue aanroept voor een eigenschap met een dynamische resource of binding (zonder letterlijke lokale waarde), wordt de dynamische resource of binding gewist.
WaardeInstellen
De methode SetCurrentValue is een andere manier om een eigenschap in te stellen, maar deze bevindt zich niet in de prioriteitslijst. Met SetCurrentValue kunt u de waarde van een eigenschap wijzigen zonder de oorspronkelijke waarde te overschrijven. Als een eigenschap bijvoorbeeld wordt ingesteld door een trigger en u vervolgens een andere waarde toewijst met behulp van SetCurrentValue, wordt de eigenschap weer ingesteld op de triggerwaarde. U kunt SetCurrentValue gebruiken wanneer u een eigenschapswaarde wilt instellen zonder deze waarde het prioriteitsniveau van een lokale waarde te geven. Op dezelfde manier kunt u SetCurrentValue gebruiken om de waarde van een eigenschap te wijzigen zonder een binding te overschrijven.
Dwang en animatie
Coercion en animatie werken beide op een basiswaarde. De basiswaarde is de waarde van de afhankelijkheidseigenschap met de hoogste prioriteit, bepaald door omhoog te evalueren via de prioriteitslijst totdat item 2 is bereikt.
Als een animatie niet zowel From als To eigenschapswaarden opgeeft voor bepaald gedrag, of als de animatie opzettelijk wordt teruggezet naar de basiswaarde wanneer deze is voltooid, kan de basiswaarde van invloed zijn op de geanimeerde waarde. Als u dit in de praktijk wilt zien, voert u de voorbeeldtoepassing Doelwaarden uit. Stel in het voorbeeld initiële lokale waarden in voor de hoogte van de rechthoek die verschillen van elke From waarde. De voorbeeldanimaties beginnen meteen met behulp van de From waarde in plaats van de basiswaarde. Als u Stop opgeeft als de FillBehavior, wordt bij voltooiing van een animatie een eigenschapswaarde opnieuw ingesteld op de basiswaarde. De normale prioriteit wordt gebruikt voor het bepalen van de basiswaarde nadat een animatie is beëindigd.
Meerdere animaties kunnen worden toegepast op één eigenschap, waarbij elke animatie een andere prioriteit heeft. In plaats van de animatie met de hoogste prioriteit toe te passen, kan de WPF-presentatie-engine de animatiewaarden samenbrengen, afhankelijk van de manier waarop de animaties zijn gedefinieerd en het type waarden met animatie. Zie Animatieoverzicht voor meer informatie
Coercion bevindt zich boven aan de prioriteitslijst. Zelfs een actieve animatie is onderhevig aan waarde-dwang. Sommige bestaande afhankelijkheidseigenschappen in WPF hebben ingebouwde dwang. Voor aangepaste afhankelijkheidseigenschappen kunt u gedrag van dwang definiëren door een CoerceValueCallback te schrijven die u doorgeeft als onderdeel van metagegevens wanneer u een eigenschap maakt. U kunt ook het dwinggedrag van bestaande eigenschappen wijzigen door de metagegevens voor die eigenschap in een afgeleide klasse aan te passen. Coercion communiceert met de basiswaarde op een zodanige manier dat de beperkingen voor dwang worden toegepast zoals ze op dat moment bestaan, maar de basiswaarde blijft behouden. Als de beperkingen in dwang later worden opgeheven, retourneert de dwang de dichtstbijzijnde waarde die mogelijk is voor de basiswaarde en wordt mogelijk de invloed van de dwang op een eigenschap beëindigd zodra alle beperkingen worden opgeheven. Voor meer informatie over coerciongedrag, zie Callbacks voor afhankelijkheidseigenschappen en validatie.
Triggergedragingen
Besturingselementen definiëren vaak triggergedrag als onderdeel van hun standaardstijl. Het instellen van lokale eigenschappen op besturingselementen kan mogelijk conflicteren met deze triggers, waardoor de triggers niet kunnen reageren (visueel of gedragsmatig) op gebruikersgestuurde gebeurtenissen. Een veelvoorkomend gebruik van een eigenschapstrigger is het beheren van statuseigenschappen, zoals IsSelected of IsEnabled. Wanneer een Button bijvoorbeeld is uitgeschakeld, stelt een themastijltrigger (IsEnabled is false) de Foreground-waarde in om de Button grijs weer te geven. Als u een lokale Foreground-waarde hebt ingesteld, heeft de lokale eigenschapswaarde met hogere prioriteit voorrang op de themastijl Foreground-waarde, ook wanneer de Button is uitgeschakeld. Wanneer u eigenschapswaarden instelt waarmee triggergedrag op themaniveau voor een besturingselement wordt overschreven, moet u ervoor zorgen dat u de beoogde gebruikerservaring voor dat besturingselement niet onnodig verstoort.
ClearValue
Met de methode ClearValue worden alle lokaal toegepaste waarden van een afhankelijkheidseigenschap voor een element gewist. Het aanroepen van ClearValue garandeert echter niet dat de standaardwaarde die tijdens de registratie van eigenschappen is ingesteld, de nieuwe effectieve waarde is. Zijn alle andere deelnemers aan de prioriteitslijst nog steeds actief, en wordt alleen de lokaal ingestelde waarde verwijderd. Als u bijvoorbeeld ClearValue aanroept voor een eigenschap met een themastijl, wordt de waarde van de themastijl toegepast als de nieuwe waarde in plaats van de standaardwaarde op basis van metagegevens. Als u een eigenschapswaarde wilt instellen op de standaardwaarde voor geregistreerde metagegevens, haalt u de standaardmetagegevens op door een query uit te voeren op de metagegevens van de afhankelijkheidseigenschap en de eigenschapswaarde lokaal in te stellen met een aanroep naar SetValue.
Zie ook
.NET Desktop feedback