Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O funcionamento do sistema de propriedades do Windows Presentation Foundation (WPF) afeta o valor de uma propriedade de dependência. Este artigo explica como a precedência de diferentes entradas baseadas em propriedade dentro do sistema de propriedades WPF determina o valor efetivo de uma propriedade de dependência.
Pré-requisitos
O artigo pressupõe um conhecimento básico das propriedades de dependência e que você leu Visão geral das propriedades de dependência. Para seguir os exemplos neste artigo, isso ajuda se você estiver familiarizado com Extensible Application Markup Language (XAML) e souber como escrever aplicativos WPF.
O sistema de propriedades WPF
O sistema de propriedades WPF usa uma variedade de fatores para determinar o valor das propriedades de dependência, como validação de propriedade em tempo real, vinculação tardia e notificações de alteração de propriedade para propriedades relacionadas. Embora a ordem e a lógica usadas para determinar os valores de propriedade de dependência sejam complexas, aprender isso pode ajudá-lo a evitar configurações de propriedade desnecessárias e também a descobrir por que uma tentativa de definir uma propriedade de dependência não resultou no valor esperado.
Propriedades de dependência definidas em vários locais
O exemplo XAML a seguir mostra como três operações "set" diferentes na propriedade do Background botão podem influenciar seu valor.
<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>
No exemplo, a Background propriedade é definida localmente como Red. No entanto, o estilo implícito declarado no escopo do botão tenta definir a Background propriedade como Blue. E, quando o rato está sobre o botão, o gatilho tenta definir a propriedade Background para Yellow no estilo implícito. Exceto para coerção e animação, um valor de propriedade definido localmente tem a maior precedência, portanto, o botão será vermelho, mesmo ao passar o mouse. Mas, se você remover o valor definido localmente do botão, ele obterá seu Background valor do estilo. Dentro de um estilo, os gatilhos têm precedência, então o botão será amarelo ao passar o mouse e azul caso contrário. O exemplo substitui o padrão ControlTemplate do botão porque o modelo padrão tem um valor de mouseover Background codificado.
Lista de precedência de propriedade de dependência
A lista a seguir é a ordem definitiva de precedência que o sistema de propriedades usa ao atribuir valores de tempo de execução a propriedades de dependência. A precedência mais alta é listada primeiro.
Coerção do sistema de propriedade. Para obter mais informações sobre coerção, consulte Coerção e animações.
Animações ativas ou animações com um comportamento de Retenção. Para ter um efeito prático, um valor de animação deve ter precedência sobre o valor base (não animado), mesmo que o valor base tenha sido definido localmente. Para obter mais informações, consulte Coerção e animações.
Valores locais. Você pode definir um valor local por meio de uma propriedade "wrapper", que equivale a definir um atributo ou elemento de propriedade em XAML, ou por uma chamada para a SetValue API usando uma propriedade de uma instância específica. Um valor local definido por meio de uma associação ou recurso terá a mesma precedência que um valor definido diretamente.
Valores da propriedade de template TemplatedParent. Um elemento tem um TemplatedParent se foi criado por um modelo (ControlTemplate ou DataTemplate). Para obter mais informações, consulte TemplatedParent. Dentro do modelo especificado pelo
TemplatedParent, a ordem de precedência é:Gatilhos.
Conjuntos de propriedades, normalmente por meio de atributos XAML.
Estilos implícitos. Aplica-se apenas à propriedade Style. O valor
Styleé qualquer recurso de estilo cujo valor TargetType corresponda ao tipo de elemento. O recurso de estilo deve existir dentro da página ou aplicativo. A pesquisa de um recurso de estilo implícito não se estende aos recursos de estilos em Temas.Gatilhos de estilo. Um gatilho de estilo é um gatilho dentro de um estilo explícito ou implícito. O estilo deve existir dentro da página ou aplicativo. Os gatilhos nos estilos padrão têm uma precedência menor.
Gatilhos de template. Um gatilho de modelo é um gatilho de um modelo aplicado diretamente ou de um modelo dentro de um estilo. O estilo deve existir dentro da página ou aplicativo.
Valores de configuração de estilo. Um valor definidor de estilo é um valor aplicado por um Setter dentro de um estilo. O estilo deve existir dentro da página ou aplicativo.
Estilos padrão, também conhecidos como estilos de tema. Para obter mais informações, consulte Estilos padrão (tema). Dentro de um estilo padrão, a ordem de precedência é:
Gatilhos ativos.
Setters.
Herança. Algumas propriedades de dependência de um elemento filho herdam seu valor do elemento pai. Portanto, pode não ser necessário definir valores de propriedade em cada elemento em todo o aplicativo. Para mais informações, consulte o item Herança de valor de propriedade.
Valor padrão dos metadados da propriedade de dependência Uma propriedade de dependência pode ter um valor padrão definido durante o registro dessa propriedade no sistema de propriedades. As classes derivadas que herdam uma propriedade de dependência podem substituir os metadados da propriedade de dependência (incluindo o valor padrão) por tipo. Para obter mais informações, consulte Metadados de propriedade de dependência. Para uma propriedade herdada, o valor padrão de um elemento pai tem precedência sobre o valor padrão de um elemento filho. Portanto, se uma propriedade hereditária não estiver definida, o valor padrão da raiz ou pai será usado em vez do valor padrão do elemento filho.
TemplatedParent
TemplatedParent A precedência não se aplica às propriedades de elementos que são declarados diretamente na marcação de aplicativo padrão. O TemplatedParent conceito existe apenas para elementos filho dentro de uma árvore visual que são criados através da aplicação de um template. Quando o sistema de propriedades pesquisa o modelo especificado pelo TemplatedParent para os valores de propriedade de um elemento, ele está pesquisando o modelo que criou o elemento. Os valores de propriedade do modelo geralmente agem como se fossem valores definidos localmente no elemento, mas com menor precedência do que os TemplatedParent valores locais reais porque os modelos são potencialmente compartilhados. Para obter mais informações, consulte TemplatedParent.
A propriedade Style
A mesma ordem de precedência aplica-se a todas as propriedades de dependência, exceto a Style propriedade. A propriedade Style é única porque não pode ser estilizada. Coagir ou animar a propriedade Style não é recomendado, e animar a propriedade Style exigiria uma classe de animação personalizada. Como resultado, nem todos os itens de precedência se aplicam. Há apenas três maneiras de definir a Style propriedade:
Estilo explícito. A
Stylepropriedade de um elemento é definida diretamente. OStylevalor da propriedade age como se fosse um valor local e tem a mesma precedência que o item 3 na lista de precedências. Na maioria dos casos, estilos explícitos não são definidos no próprio código e, em vez disso, são explicitamente referenciados como um recurso, por exemploStyle="{StaticResource myResourceKey}".Estilo implícito. A
Stylepropriedade de um elemento não é definida diretamente. Em vez disso, um estilo é aplicado quando existe em algum nível dentro da página ou aplicativo e tem uma chave de recurso que corresponde ao tipo de elemento ao qual o estilo se aplica, por exemplo<Style TargetType="x:Type Button">. O tipo deve corresponder exatamente, por exemplo<Style TargetType="x:Type Button">, não será aplicado aoMyButtontipo, mesmo queMyButtonseja derivado deButton. OStylevalor da propriedade tem a mesma precedência que o item 5 na lista de precedências. Pode-se detetar um valor de estilo implícito ao chamar o método DependencyPropertyHelper.GetValueSource, passando na propriedadeStylee verificandoImplicitStyleReferencenos resultados.Estilo padrão, também conhecido como estilo de tema. A
Stylepropriedade de um elemento não é definida diretamente. Em vez disso, ele vem da avaliação do tema em tempo de execução pelo mecanismo de apresentação do WPF. Antes do tempo de execução, o valor daStylepropriedade énull. OStylevalor da propriedade tem a mesma precedência que o item 9 na lista de precedências.
Estilos padrão (tema)
Cada controle fornecido com o WPF tem um estilo padrão que pode variar de acordo com o tema, e é por isso que o estilo padrão às vezes é referido como um estilo de tema.
O ControlTemplate é um item importante dentro do estilo padrão para um controle.
ControlTemplate é um definidor de valor para a propriedade de estilo Template. Se os estilos padrão não contivessem um modelo, um controle sem um modelo personalizado como parte de um estilo personalizado não teria aparência visual. Um modelo não apenas define a aparência visual de um controle, mas também define as conexões entre as propriedades na árvore visual do modelo e a classe de controle correspondente. Cada controle expõe um conjunto de propriedades que podem influenciar a aparência visual do controle sem substituir o modelo. Por exemplo, considere a aparência visual padrão de um Thumb controle, que é um ScrollBar componente.
Um Thumb controle tem certas propriedades personalizáveis. O modelo padrão de um controlo Thumb cria uma estrutura básica, ou árvore visual, composta por vários Border componentes aninhados que geram uma aparência chanfrada. Dentro do modelo, as propriedades que se destinam a ser personalizáveis pela classe são expostas por meio de ThumbTemplateBinding
Os estilos padrão especificam a TargetType em suas definições. A avaliação do tema em tempo de execução relaciona o TargetType de um estilo padrão à propriedade DefaultStyleKey de um controlo. Em contraste, o método de busca para estilos implícitos usa o tipo real do controle. O valor de DefaultStyleKey é herdado por classes derivadas, de modo que os elementos derivados que, de outra forma, poderiam não ter nenhum estilo associado obtêm uma aparência visual padrão. Por exemplo, se você derivar MyButton de Button, MyButton herdará o modelo padrão de Button. As classes derivadas podem substituir o valor padrão nos metadados da propriedade de dependência DefaultStyleKey. Portanto, se quiseres uma representação visual diferente para MyButton, podes substituir os metadados da propriedade de dependência em DefaultStyleKey em MyButton e, em seguida, definir o estilo padrão relevante, incluindo um modelo, que empacotarás com o teu controlo MyButton. Para obter mais informações, consulte Visão geral da criação de controle
Recurso dinâmico
As referências de recursos dinâmicos não fazem tecnicamente parte do sistema de propriedades e têm sua própria ordem de pesquisa que interage com a lista de precedências. Essencialmente, a precedência das referências de recursos dinâmicos é: elemento para raiz de página, aplicativo, tema e, em seguida, sistema. Para obter mais informações, consulte Recursos XAML.
Embora as referências e associações de recursos dinâmicos tenham a precedência do local no qual são definidas, o valor é adiado. Uma consequência disso é que, se você definir um recurso dinâmico ou uma ligação a um valor local, qualquer alteração no valor local substituirá inteiramente o recurso dinâmico ou a ligação. Mesmo que você chame o ClearValue método para limpar o valor definido localmente, o recurso dinâmico ou a associação não será restaurado. Na verdade, se chamar ClearValue numa propriedade que tenha um recurso dinâmico ou uma ligação (sem um valor local literal), o recurso dinâmico ou a ligação será eliminado.
DefinirValorAtual
O SetCurrentValue método é outra maneira de definir uma propriedade, mas não está na lista de precedências.
SetCurrentValue Permite alterar o valor de uma propriedade sem substituir a origem de um valor anterior. Por exemplo, se uma propriedade for definida por um gatilho e, em seguida, você atribuir outro valor usando SetCurrentValue, a próxima ação de gatilho definirá a propriedade de volta para o valor do gatilho. Você pode usar SetCurrentValue sempre que quiser definir um valor de propriedade sem dar a esse valor o nível de precedência de um valor local. De igual modo, pode usar SetCurrentValue para alterar o valor de uma propriedade sem substituir uma vinculação.
Coerção e animação
Tanto a coerção como a animação atuam sobre um valor base. O valor base é o valor da propriedade de dependência com a maior precedência, determinado avaliando para cima através da lista de precedência até que o item 2 seja alcançado.
Se uma animação não especificar valores de propriedade From e To ambos para determinados comportamentos, ou se a animação deliberadamente reverter para o valor base quando concluída, o valor base poderá afetar o valor animado. Para ver isso na prática, execute o aplicativo de exemplo Valores de destino . No exemplo, para a altura do retângulo, tente definir valores locais iniciais que diferem de qualquer From valor. As animações de exemplo começam imediatamente usando o From valor em vez do valor base. Ao especificar Stop como FillBehavior, após concluir, uma animação redefinirá o valor de uma propriedade para o seu valor base. A precedência normal é usada para a determinação do valor base após o término de uma animação.
Várias animações podem ser aplicadas a uma única propriedade, com cada animação tendo uma precedência diferente. Em vez de aplicar a animação com a maior precedência, o mecanismo de apresentação do WPF pode compor os valores de animação, dependendo de como as animações foram definidas e do tipo de valores animados. Para obter mais informações, consulte Visão geral da animação
A coerção está no topo da lista de precedências. Mesmo uma animação em execução está sujeita a coerção de valor. Algumas propriedades de dependência existentes no WPF têm coerção incorporada. Para propriedades de dependência personalizadas, você pode definir o comportamento de coerção escrevendo um CoerceValueCallback que você passa como parte dos metadados ao criar uma propriedade. Você também pode substituir o comportamento de coerção de propriedades existentes substituindo os metadados dessa propriedade em uma classe derivada. A coerção interage com o valor base de tal forma que as restrições à coerção são aplicadas tal como existem no momento, mas o valor base ainda é mantido. Como resultado, se as restrições na coerção forem posteriormente levantadas, a coerção retornará o valor mais próximo possível do valor base e, potencialmente, a influência da coerção sobre uma propriedade cessará assim que todas as restrições forem levantadas. Para obter mais informações sobre o comportamento coercitivo, consulte Retornos de chamada e validação de propriedade de dependência.
Comportamentos de gatilho
Os controles geralmente definem comportamentos de gatilho como parte de seu estilo padrão. Definir propriedades locais em controles pode entrar em conflito com esses gatilhos, impedindo que os gatilhos respondam (visual ou comportamentalmente) a eventos controlados pelo usuário. Um uso comum de um gatilho de propriedade é controlar propriedades de estado, como IsSelected ou IsEnabled. Por exemplo, por padrão, quando um Button está desativado, um gatilho de estilo de tema (IsEnabled is false) define o Foreground valor para fazer com que o Button apareça acinzentado. Se você tiver definido um valor local Foreground , o valor da propriedade local de precedência mais alta anulará o valor do estilo Foreground do tema, mesmo quando o Button estiver desabilitado. Ao definir valores de propriedade que substituem comportamentos de gatilho no nível do tema para um controle, tenha cuidado para não interferir indevidamente na experiência do usuário pretendida para esse controle.
ClearValue
O ClearValue método limpa qualquer valor aplicado localmente de uma propriedade de dependência para um elemento. Mas, a chamada ClearValue não garante que o valor padrão estabelecido nos metadados durante o registro do imóvel seja o novo valor efetivo. Todos os outros participantes na lista de precedência ainda estão ativos e apenas o valor definido localmente é removido. Por exemplo, se você chamar ClearValue uma propriedade que tenha um estilo de tema, o valor do estilo de tema será aplicado como o novo valor, em vez do padrão baseado em metadados. Se você quiser definir um valor de propriedade para o valor padrão de metadados registrados, obtenha o valor de metadados padrão consultando os metadados da propriedade de dependência e defina localmente o valor da propriedade com uma chamada para SetValue.
Ver também
.NET Desktop feedback