Precedência de valores de propriedade de dependência
This topic explains how the workings of the Windows Presentation Foundation (WPF) property system can affect the value of a dependency property, and describes the precedence by which aspects of the property system apply to the effective value of a property.
Este tópico contém as seguintes seções.
- Prerequisites
- The WPF Property System
- Dependency Properties Might Be "Set" in Multiple Places
- Dependency Property Setting Precedence List
- TemplatedParent
- The Style Property
- Default (Theme) Styles
- Dynamic Resource References and Binding
- SetCurrentValue
- Coercion, Animations, and Base Value
- Trigger Behaviors
- ClearValue and Value Precedence
- Tópicos relacionados
Prerequisites
Este tópico pressupõe que você compreenda as propriedades de dependência da perspectiva de um consumidor de propriedades de dependência existente em WPF classes e leu Visão geral sobre propriedades de dependência. To follow the examples in this topic, you should also understand Extensible Application Markup Language (XAML) and know how to write WPF applications.
The WPF Property System
O WPF o sistema de propriedade oferece uma maneira eficiente de se ter o valor das propriedades de dependência ser determinado por uma variedade de fatores, habilitando recursos como validação de propriedade em tempo real, atrasado ligação e notificar propriedades relacionadas de alterações em valores de outras propriedades. The exact order and logic that is used to determine dependency property values is reasonably complex. Knowing this order will help you avoid unnecessary property setting, and might also clear up confusion over exactly why some attempt to influence or anticipate a dependency property value did not end up resulting in the value you expected.
Dependency Properties Might Be "Set" in Multiple Places
The following is example XAML where the same property (Background) has three different "set" operations that might influence the value.
<Button Background="Red">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
Click
</Button>
Here, which color do you expect will apply—red, green, or blue?
With the exception of animated values and coercion, local property sets are set at the highest precedence. If you set a value locally you can expect that the value will be honored, even above any styles or control templates. Here in the example, Background is set to Red locally. Therefore, the style defined in this scope, even though it is an implicit style that would otherwise apply to all elements of that type in that scope, is not the highest precedence for giving the Background property its value. If you removed the local value of Red from that Button instance, then the style would have precedence and the button would obtain the Background value from the style. Within the style, triggers take precedence, so the button will be blue if the mouse is over it, and green otherwise.
Dependency Property Setting Precedence List
The following is the definitive order that the property system uses when assigning the run-time values of dependency properties. Highest precedence is listed first. This list expands on some of the generalizations made in the Visão geral sobre propriedades de dependência.
Property system coercion. Para obter detalhes sobre a coerção, consulte coerção, animação e o valor de Base posteriormente neste tópico.
Active animations, or animations with a Hold behavior. In order to have any practical effect, an animation of a property must be able to have precedence over the base (unanimated) value, even if that value was set locally. For details, see Coercion, Animation, and Base Value later in this topic.
Local value. Um valor de local pode ser definido através a conveniência do "wrapper" propriedade, que também é igual à configuração como um elemento de atributo ou propriedade em XAML, ou por uma chamada para o SetValue API usando uma propriedade de uma instância específica. If you set a local value by using a binding or a resource, these each act in the precedence as if a direct value was set.
TemplatedParent template properties. Um elemento tem um TemplatedParent se ele foi criado como parte de um modelo (um ControlTemplate ou DataTemplate). For details on when this applies, see TemplatedParent later in this topic. Within the template, the following precedence applies:
Triggers from the TemplatedParent template.
Property sets (typically through XAML attributes) in the TemplatedParent template.
Implicit style. Só é aplicável a Style propriedade. The Style property is filled by any style resource with a key that matches the type of that element. That style resource must exist either in the page or the application; lookup for an implicit style resource does not proceed into the themes.
Style triggers. The triggers within styles from page or application (these styles might be either explicit or implicit styles, but not from the default styles, which have lower precedence).
Template triggers. Any trigger from a template within a style, or a directly applied template.
Style setters. Valores de um Setter dentro de estilos de página ou aplicativo.
Default (theme) style. Para obter detalhes sobre quando isso se aplica, e como os estilos de tema se relacionam com os modelos de estilos do tema, consulte estilos padrão (tema) posteriormente neste tópico. Within a default style, the following order of precedence applies:
Active triggers in the theme style.
Setters in the theme style.
Herança. A few dependency properties inherit their values from parent element to child elements, such that they need not be set specifically on each element throughout an application. For details see Herança de Valor de Propriedade.
Default value from dependency property metadata. Any given dependency property may have a default value as established by the property system registration of that particular property. Also, derived classes that inherit a dependency property have the option to override that metadata (including the default value) on a per-type basis. See Metadados de Propriedade de Dependência for more information. Because inheritance is checked before default value, for an inherited property, a parent element default value takes precedence over a child element. Consequently, if an inheritable property is not set anywhere, the default value as specified on the root or parent is used instead of the child element default value.
TemplatedParent
TemplatedParent as a precedence item does not apply to any property of an element that you declare directly in standard application markup. The TemplatedParent concept exists only for child items within a visual tree that come into existence through the application of the template. When the property system searches the TemplatedParent template for a value, it is searching the template that created that element. The property values from the TemplatedParent template generally act as if they were set as a local value on the child element, but this lesser precedence versus the local value exists because the templates are potentially shared. For details, see TemplatedParent.
The Style Property
A ordem de pesquisa descrita anteriormente aplica-se a todas as propriedades de dependência possíveis, exceto um: o Style propriedade. The Style property is unique in that it cannot itself be styled, so the precedence items 5 through 8 do not apply. Also, either animating or coercing Style is not recommended (and animating Style would require a custom animation class). This leaves three ways that the Style property might be set:
Explicit style. O Style propriedade é definida diretamente. In most scenarios, the style is not defined inline, but instead is referenced as a resource, by explicit key. In this case the Style property itself acts as if it were a local value, precedence item 3.
Implicit style. O Style propriedade não está definida diretamente. However, the Style exists at some level in the resource lookup sequence (page, application) and is keyed using a resource key that matches the type the style is to be applied to. Nesse caso, o Style própria propriedade age por uma precedência identificada na seqüência como item 5. Essa condição pode ser detectada por meio de DependencyPropertyHelper contra o Style de propriedade e procurando ImplicitStyleReference em resultados.
Default style, also known as theme style. The Style property is not set directly, and in fact will read as null up until run time. In this case, the style comes from the run-time theme evaluation that is part of the WPF presentation engine.
For implicit styles not in themes, the type must match exactly—a MyButton Button-derived class will not implicitly use a style for Button.
Default (Theme) Styles
Every control that ships with WPF has a default style. That default style potentially varies by theme, which is why this default style is sometimes referred to as a theme style.
The most important information that is found within a default style for a control is its control template, which exists in the theme style as a setter for its Template property. If there were no template from default styles, a control without a custom template as part of a custom style would have no visual appearance at all. The template from the default style gives the visual appearance of each control a basic structure, and also defines the connections between properties defined in the visual tree of the template and the corresponding control class. Each control exposes a set of properties that can influence the visual appearance of the control without completely replacing the template. Por exemplo, considere a aparência visual do padrão de um Thumb controle, que é um componente de um ScrollBar.
A Thumb has certain customizable properties. The default template of a Thumb creates a basic stucture / visual tree with several nested Border components to create a bevel look. If a property that is part of the template is intended to be exposed for customization by the Thumb class, then that property must be exposed by a TemplateBinding, within the template. In the case of Thumb, various properties of these borders share a template binding to properties such as Background or BorderThickness. But certain other properties or visual arrangements are hard-coded into the control template or are bound to values that come directly from the theme, and cannot be changed short of replacing the entire template. Generally, if a property comes from a templated parent and is not exposed by a template binding, it cannot be adjusted by styles because there is no easy way to target it. But that property could still be influenced by property value inheritance in the applied template, or by default value.
The theme styles use a type as the key in their definitions. However, when themes are applied to a given element instance, themes lookup for this type is performed by checking the DefaultStyleKey property on a control. Isso é em contraste com o uso do tipo literal, como estilos implícitos. O valor de DefaultStyleKey herdaria a classes derivadas, mesmo se o implementador não foi alterado (a maneira pretendida de alteração da propriedade é não para substituí-la no nível da propriedade, mas em vez disso, alteração de metadados da propriedade valor padrão). This indirection enables base classes to define the theme styles for derived elements that do not otherwise have a style (or more importantly, do not have a template within that style and would thus have no default visual appearance at all). Thus, you can derive MyButton from Button and will still get the Button default template. If you were the control author of MyButton and you wanted a different behavior, you could override the dependency property metadata for DefaultStyleKey on MyButton to return a different key, and then define the relevant theme styles including template for MyButton that you must package with your MyButton control. For more details on themes, styles, and control authoring, see Visão geral sobre criação de controles.
Dynamic Resource References and Binding
Referências de recurso dinâmico e operações de vinculação respeitam a precedência do local em que são definidas. Por exemplo, um recurso dinâmico aplicado a um valor local funciona por item de precedência 3, uma ligação para um setter de propriedade dentro de um estilo de tema aplica-se no item de prioridade 9 e assim por diante. Because dynamic resource references and binding must both be able to obtain values from the run time state of the application, this entails that the actual process of determining the property value precedence for any given property extends into the run time as well.
Dynamic resource references are not strictly speaking part of the property system, but they do have a lookup order of their own which interacts with the sequence listed above. That precedence is documented more thoroughly in the Visão geral sobre Recursos. A soma básica de que a precedência é: elemento de raiz de página, o aplicativo, o tema, o sistema.
Ligações e recursos dinâmicos a precedência de onde elas foram definidas, mas o valor é adiado. Uma conseqüência disso é que, se você definir um recurso dinâmico ou vinculando a um valor de local, qualquer alteração no valor de local substitui o recurso dinâmico ou ligação inteiramente. Mesmo se você chamar o ClearValue método para limpar o definido localmente valor, o recurso dinâmico ou ligação não será restaurada. Na verdade, se você chamar ClearValue em uma propriedade que tem um recurso dinâmico ou ligação no lugar (com nenhum valor literal de local), são apagadas utilizando o ClearValue chamada muito.
SetCurrentValue
O SetCurrentValue método é outra maneira de definir uma propriedade, mas não na ordem de precedência. Em vez disso, SetCurrentValue permite que você altere o valor de uma propriedade sem substituir a origem do valor anterior. Você pode usar SetCurrentValue qualquer momento que você deseja definir um valor sem dar esse valor a precedência de um valor de local. Por exemplo, se uma propriedade é definida por um disparador e, então, atribuída a outro valor por meio de SetCurrentValue, o sistema de propriedade ainda respeita o disparador e a propriedade será alterada se ocorrer a ação do disparador. SetCurrentValuepermite que você altere o valor da propriedade sem dar a ele uma fonte com uma precedência mais alta. Da mesma forma, você pode usar SetCurrentValue para alterar o valor de uma propriedade sem substituir uma ligação.
Coercion, Animations, and Base Value
Coercion and animation both act on a value that is termed as the "base value" throughout this SDK. The base value is thus whatever value is determined through evaluating upwards in the items until item 2 is reached.
For an animation, the base value can have an effect on the animated value, if that animation does not specify both "From" and "To" for certain behaviors, or if the animation deliberately reverts to the base value when completed. Para ver isso na prática, execute o partir e por amostra de valores de destino de animação. Try setting the local values of the rectangle height in the example, such that the initial local value differs from any "From" in the animation. You will note that the animations start right away using the "From" values and replace the base value once started. The animation might specify to return to the value found before animation once it is completed by specifying the Stop FillBehavior. Afterwards, normal precedence is used for the base value determination.
Multiple animations might be applied to a single property, with each of these animations possibly having been defined from different points in the value precedence. However, these animations will potentially composite their values, rather than just applying the animation from the higher precedence. This depends on exactly how the animations are defined, and the type of the value that is being animated. For more information about animating properties, see Revisão de Animação.
Coercion applies at the highest level of all. Even an already running animation is subject to value coercion. Certain existing dependency properties in WPF have built-in coercion. For a custom dependency property, you define the coercion behavior for a custom dependency property by writing a CoerceValueCallback and passing the callback as part of metadata when you create the property. You can also override coercion behavior of existing properties by overriding the metadata on that property in a derived class. Coercion interacts with the base value in such a way that the constraints on coercion are applied as those constraints exist at the time, but the base value is still retained. Therefore, if constraints in coercion are later lifted, the coercion will return the closest value possible to that base value, and potentially the coercion influence on a property will cease as soon as all constraints are lifted. For more information about coercion behavior, see Validação e Callbacks de Propriedade de Dependência.
Trigger Behaviors
Controls often define trigger behaviors as part of their default style in themes. Setting local properties on controls might prevent the triggers from being able to respond to user-driven events either visually or behaviorally. The most common use of a property trigger is for control or state properties such as IsSelected. Por exemplo, por padrão quando um Button está desativado (disparar para IsEnabled é false), em seguida, o Foreground o valor do estilo do tema é o que faz com que o controle apareça "acinzentada". But if you have set a local Foreground value, that normal gray-out color will be overruled in precedence by your local property set, even in this property-triggered scenario. Be cautious of setting values for properties that have theme-level trigger behaviors and make sure you are not unduly interfering with the intended user experience for that control.
ClearValue and Value Precedence
The ClearValue method provides an expedient means to clear any locally applied value from a dependency property that is set on an element. However, calling ClearValue is not a guarantee that the default as established in metadata during property registration is the new effective value. All of the other participants in value precedence are still active. Only the locally set value has been removed from the precedence sequence. Por exemplo, se você chamar ClearValue em uma propriedade onde essa propriedade também é definida por um estilo de tema, e o valor de tema é aplicado como o novo valor em vez de baseados em metadados padrão. If you want to take all property value participants out of the process and set the value to the registered metadata default, you can obtain that default value definitively by querying the dependency property metadata, and then you can use the default value to locally set the property with a call to SetValue.
Consulte também
Referência
Conceitos
Visão geral sobre propriedades de dependência