Exportar (0) Imprimir
Expandir Tudo
Este artigo foi traduzido por máquina. Coloque o ponteiro do mouse sobre as frases do artigo para ver o texto original. Mais informações.
Tradução
Original

Precedência do valor de propriedade da dependência

Este tópico explica como o funcionamento do sistema de propriedades do Windows Presentation Foundation (WPF) pode afetar o valor de uma propriedade de dependência e descreve a precedência pela qual aspectos do sistema de propriedades se aplicadam ao valor efetivo de uma propriedade.

Este tópico contém as seções a seguir.

Este tópico assume que você entende propriedades de dependência da perspectiva de um consumidor de propriedades de dependência existentes nas classes do WPF , e já leu Visão geral de propriedades da dependência. Para que você siga os exemplos deste tópico, você também deve entender Extensible Application Markup Language (XAML) e saber como escrever aplicações WPF.

O WPF sistema de propriedades oferece uma maneira eficiente para que o valor das propriedades de dependência ser determinado por uma variedade de fatores, que habilita recursos como validação de propriedade em tempo real, atrasado ligação e notificar propriedades relacionadas de alterações em valores de outras propriedades. A ordem exata e a lógica que são usadas para determinar os valores de propriedades de dependência são razoavelmente complexas. Conhecer esta ordem irá ajudá-lo a evitar definições desnecessárias de propriedades, e pode também clarificar confusões sobre exatamente porque alguma tentativa de prever ou influenciar o valor de uma propriedade de dependência não acabou resultando no valor esperado.

A seguir temos um exemplo de XAML onde a mesma propriedade (Background) tem três diferentes operações de "definição" que podem influenciar seu valor.


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


Aqui, que cor você espera que seja aplicada — vermelho, verde ou azul?

Com exceção de valores animados e coerção, definições locais de propriedade são definidas com precedência mais alta. Se você definir um valor localmente, você pode esperar que o valor seja aceito, até mesmo acima de quaisquer estilos ou modelos de controle. No exemplo, o Background é definido localmente como vermelho. Portanto, o estilo definido neste escopo, mesmo sendo um estilo implícito que de outro modo seria aplicado a todos os elementos desse tipo nesse escopo, não tem a precedência mais alta para dar à propriedade Background seu valor. Se você removesse o valor vermelho local da instância do botão, então, o estilo teria precedência e o botão obteria o valor de plano de fundo do estilo. No estilo, os disparadores têm precedência, portanto o botão será azul se o mouse estiver sobre ele, e verde caso contrário.

A ordem a seguir é a ordem definitiva que o sistema de propriedades usa para atribuir os valores das propriedades de dependência em tempo de execução. As precedências mais altas são listadas primeiro. Esta lista se expande em algumas das generalizações feitas no Visão geral de propriedades da dependência.

  1. Coerção do sistema de propriedades Para obter detalhes sobre a coerção, consulte coerção, animação e o valor de Base posteriormente neste tópico.

  2. Animações ativas, ou animações com comportamento em espera. Para poder ter qualquer efeito prático, uma animação de uma propriedade deve ser capaz de ter precedência sobre o valor base (não animado), mesmo se esse valor foi definido localmente. Para obter detalhes, consulte Coerção, animação e valor base posteriormente neste tópico.

  3. Valor local. Um valor local pode ser definido através a conveniência da propriedade "wrapper", que também é igual à configuração como um elemento de atributo ou propriedade em XAML, ou por uma chamada para o SetValueAPI usando uma propriedade de uma instância específica.  Se você definir um valor local usando associação ou um recurso, cada um esses atua na precedência como se um valor direto fosse definido.

  4. Propriedades de modelo TemplatedParent. Um elemento tem um TemplatedParent se ele foi criado como parte de um modelo (um ControlTemplate ou DataTemplate). Para obter detalhes sobre quando isso se aplica, consulte TemplatedParent posteriormente neste tópico. Dentro do modelo, a precedência a seguir se aplica:

    1. Disparadores do modelo TemplatedParent.

    2. Definições de propriedades (geralmente através de atributos XAML) no modelo TemplatedParent.

  5. Estilo implícito. Só é aplicável a Style propriedade. A propriedade Style é preenchida por qualquer recurso de estilo com uma chave que corresponda ao tipo de elemento. Esse recurso de estilo deve existir na página ou no aplicativo; a pesquisa por um recurso de estilo implícito não prossegue nos temas.

  6. Disparadores de estilos. Os disparadores em estilos de página ou de aplicativo (esses estilos podem ser estilos explícitos ou implícitos, mas não os estilos padrão, os quais têm prioridade mais baixa).

  7. Disparadores de modelo. Qualquer disparador de um modelo em um estilo, ou de um modelo aplicado diretamente.

  8. Estilo de Setters. Os valores de um Setter dentro de estilos de página ou aplicativo.

  9. O estilo padrão (tema). 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. Em um estilo padrão, a ordem de precedência a seguir se aplica:

    1. Disparadores ativos no estilo de tema.

    2. Setters no estilo de tema.

  10. Herança. Algumas propriedades de dependência herdam seus valores de elemento pai para elementos filho, de forma que eles não precisam ser definidos especificamente em cada elemento em um aplicativo. Para mais detalhes, consulte Herança do valor de propriedade

  11. Valor padrão de metadados de propriedades de dependência. Qualquer propriedade de dependência pode ter um valor padrão conforme estabelecido pelo sistema de registro de propriedades daquela determinada propriedade. Além disso, classes derivadas que herdam uma propriedade de dependência têm a opção de sobrescrever esses metadados (inclusive o valor padrão) por tipo. Consulte Metadados de propriedade da dependência para obter mais informações. Como a herança é verificada antes do valor padrão, para uma propriedade herdada, o valor padrão de um elemento pai tem precedência sobre o de um elemento filho. Consequentemente, se uma propriedade herdável não é definida em qualquer lugar, o valor padrão conforme especificado na raiz ou no pai será usado em vez do valor padrão no elemento filho.

TemplatedParent não se aplica como um item precedência a qualquer propriedade de um elemento que você declarar diretamente em linguagem padrão de marcação de aplicativos. O conceito de TemplatedParent existe somente para itens filho em uma árvore visual que passa a existir através da aplicação de um modelo. Quando o sistema de propriedades procura o modelo TemplatedParent para um valor, ele está procurando pelo modelo que criou esse elemento. Os valores de propriedade do modelo TemplatedParent geralmente agem como se eles tivessem sido definidos como um valor local no elemento filho, mas essa menor precedência em relação ao valor local existe pois modelos são potencialmente compartilhados. Para obter detalhes, consulte:TemplatedParent.

A ordem de consulta descrita anteriormente se aplica a todas as possíveis propriedades de dependência, exceto uma: a propriedade Style. A propriedade Style é exclusiva em que não pode ser ela própria estilizada, portanto, os itens de precedência de 5 a 8 não se aplicam. Além disso, animação ou coerção de Style não são recomendadas (e animar um Style exigiria uma classe de animação personalizada). Isso deixa três maneiras em que a propriedade Style pode ser definida:

  • Estilo explícito. O Style propriedade é definida diretamente. Na maioria das situações o estilo não é definido de forma embutida, mas, em vez disso, é referenciado como um recurso, por chave explícita. Nesse caso, a própria propriedade Style atua como se fosse um valor local, item 3 de precedência.

  • Estilo implícito. O Style propriedade não está definida diretamente. No entanto, o Style existe em algum nível na sequência de consulta por recursos (página, aplicativo) e é associado a uma chave de recurso que corresponde ao tipo ao qual o estilo for ser aplicado. Nesse caso, o Style própria propriedade age, 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 nos resultados.

  • O estilo padrão, também conhecido como estilo tema. A propriedade Style não é definida diretamente e na verdade é lida como null até chegar em tempo de execução. Nesse caso, o estilo vem da avaliação em tempo de execução do tema que faz parte do mecanismo de apresentação do WPF.

Para estilos implícitos não em temas, o tipo deve coincidir exatamente — uma classe MyButton derivada de Button não vai implicitamente usar um estilo para Button.

Cada controle que acompanha o WPF tem um estilo padrão. Esse estilo padrão potencialmente varia por tema, o que faz com que este estilo padrão seja algumas vezes conhecido como um estilo de tema.

A informação mais importantes encontrada em um estilo padrão para um controle é seu modelo de controle, que existe no estilo de tema como um Setter para sua propriedade Template. Se não houvesse nenhum modelo vindo dos estilos padrão, um controle sem um modelo personalizado como parte de um estilo personalizado não teria nenhuma aparência. O modelo do estilo padrão fornece uma estrutura básica à aparência visual de cada controle e também define as conexões entre as propriedades definidas 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 totalmente o modelo. Por exemplo, considere a aparência visual do padrão de um Thumb controle, que é um componente de um ScrollBar.

Um Thumb possui certas propriedades personalizáveis. O modelo padrão de um Thumb cria uma árvore visual/estrutura básica com vários componentes Border aninhados para criar uma aparência de alto relevo. Se uma propriedade que é parte do modelo se destina a ser exposta para personalização pela classe Thumb, então essa propriedade deve ser exposta por um TemplateBinding dentro do modelo. No caso de Thumb, várias propriedades dessas bordas compartilham um modelo fazendo associação a propriedades como Background ou BorderThickness. Mas determinadas outras propriedades ou disposições visuais são definidas embutidas no modelo de controle ou são associadas a valores provenientes diretamente do tema; e não podem ser alteradas a não ser que se substitua o modelo inteiro. Geralmente, se uma propriedade vem de um pai "templated" e não é exposta por uma associação de modelo, ela não pode ser ajustada por estilos pois não há uma maneira fácil de definí-la como alvo. Mas essa propriedade pode ainda ser influenciada por herança de valor de propriedade no modelo aplicado, ou pelo valor padrão.

Os estilos de tema usam um tipo como chave em suas definições. No entanto, quando os temas são aplicados a uma determinada instância de um elemento, a consulta de temas para esse tipo é executada verificando-se a propriedade DefaultStyleKey em um controle. Isso é em contraste com usando o tipo literal, como estilos implícitos. O valor de DefaultStyleKey herdaria a classes derivadas, mesmo que o implementador não foi alterado (a forma pretendida de alteração da propriedade é não para substituí-la no nível da propriedade, mas em vez disso, alteração do valor padrão nos metadados de propriedade). Essa indireção permite que classes base definam os tema de estilos para elementos derivado que não tenham um estilo (ou, mais importante, não tenham um modelo dentro desse estilo e assim não têm nenhuma aparência visual padrão). Assim, você pode fazer MyButton derivar de Button e ainda receber o modelo padrão de Button. Se você fosse o autor do controle MyButton e você quisesse um comportamento diferente, você poderia sobrescrever os metadados da propriedade de dependência de DefaultStyleKey em MyButton para retornar uma chave diferente e, em seguida, definir os estilos de tema relevantes, inclusive o modelo para MyButton que você deve empacotar com o controle MyButton. Para obter mais detalhes sobre temas, estilos e criação de controles, consulte Visão geral da criação de controle.

Referências de recursos dinâmicos e as operações de vinculação respeitam a precedência do local em que elas 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 em precedência item 9 e assim por diante. Como tanto referências dinâmicas a recursos quanto asociações devem ser capazes de obter valores do estado do aplicativo em tempo de execução, isso implica que o processo de determinar a precedência de valor de propriedades para uma dada propriedade se estende ao tempo de execução também.

Referências dinâmicas a recursos não são, estritamente falando, parte do sistema de propriedades, mas têm uma ordem de consulta específica que interage com a sequência listada acima. Essa precedência está documentada mais detalhadamente em Recursos XAML. O resumo básico dessa precedência é: elemento, raiz de página, aplicativo, tema, sistema.

Recursos dinâmicos e ligações têm 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 possui um recurso dinâmico ou ligação no local (com nenhum valor literal de local), são apagadas utilizando o ClearValue chamar muito.

O SetCurrentValue método é outra maneira de definir uma propriedade, mas não está na ordem de precedência. Em vez disso, SetCurrentValue permite que você altere o valor de uma propriedade sem substituir a fonte de um 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, em seguida, 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. SetCurrentValue permite 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.

Tanto coerção quanto animação agem em um valor que é chamado de "valor base" em todo este SDK. O valor base é, portanto, qualquer valor determinado através da avaliação dos itens até que o item 2 é alcançado.

Para uma animação, o valor base pode ter um efeito sobre o valor animado se essa animação não especificar o "From" e o "To" para certos comportamentos, ou se a animação deliberadamente reverte de volta ao valor base quando concluída. Para ver isso na prática, execute o de, para e por amostra de valores de destino de animação. Tente configurar os valores locais da altura do retângulo no exemplo, de modo que o valor local inicial fique diferente de qualquer "From" na animação. Você notará que as animações se iniciam imediatamente usando os valores de "From" e substituem o valor base depois de iniciadas. A animação pode especificar o retorno para o valor encontrado antes da animação depois que ela é concluída, especificando o comportamento de parada FillBehavior. Posteriormente, a precedência normal é usada para a determinação do valor base.

Várias animações podem ser aplicadas a uma única propriedade, com cada uma dessas animações possivelmente tendo sido definida a partir de diferentes pontos na precedência de valor. No entanto, esses animações potencialmente irão compor seus valores, em vez de apenas aplicar a animação de precedência mais alta. Isso depende de como exatamente as animações são definidas e do tipo do valor que está sendo animado. Para mais informações sobre animar propriedades, consulte Visão geral da animação.

Coerção se aplica no nível mais alto de todos. Até mesmo uma animação já em execução está sujeita a coerção de valor. Certas propriedades de dependência existentes no WPF tem coerção interna. Para uma propriedade de dependência personalizada, você define o comportamento de coerção ao escrever um CoerceValueCallback e passar a callback como parte dos metadados ao criar a propriedade. Você também pode sobrescrever o comportamento de coerção de propriedades existentes, substituindo os metadados dessas propriedades em um classe derivada. Coerção interage com o valor base de tal forma que as restrições em coerção são aplicadas como essas restrições se encontram no momento, mas o valor base ainda é mantido. Portanto, se as restrições de coerção são posteriores levantadas, a coerção irá retornar o valor mais próximo possível do valor base; e potencialmente a influência da coerção em uma propriedade acabará assim que todas as restrições sejam levantadas. Para obter mais informações sobre o comportamento de coerção, consulte Retornos de chamada da propriedade de dependência e validação.

Controles geralmente definem o comportamento de disparadores como parte do seu estilo padrão em temas. A definição de propriedades locais nos controles pode impedir que os disparadores possam responder visualmente ou comportamentalmente a eventos causados pelo usuário. O uso mais comum de um disparador de propriedade é para propriedades de controle ou estado como IsSelected. Por exemplo, por padrão quando um Button está desativado (disparar para IsEnabled é false), em seguida, o Foreground valor no estilo do tema é o que faz com que o controle apareça "acinzentada". Mas se você tiver definido um valor local para Foreground, a cor cinza normal será ignorada pela precedência da sua definição local da propriedade, mesmo nesse cenário com disparador de propriedade. Seja cuidadoso ao definir valores para propriedades que possuem comportamentos de disparador no nível de tema, e certifique-se de que você não está interferindo impropriamente com o experiência do usuário pretendida para o controle.

O método ClearValue fornece que uma maneira rápida para limpar qualquer valor aplicado localmente a uma propriedade de dependência definida em um elemento. No entanto, chamar ClearValue não garante que o valor padrão (conforme estabelecido nos metadados durante o registro da propriedade) será o novo valor efetivo. Todos os outros participantes na precedência de valor ainda estão ativos. Somente o valor definido localmente foi removido da sequência de precedência. Por exemplo, se você chamar ClearValue em uma propriedade onde essa propriedade também é definida por um estilo de tema, em seguida, o valor de tema é aplicado como o novo valor, em vez do padrão com base em metadados. Se você deseja retirar todos valores de propriedade do processo e definir o valor como sendo o padrão nos metadados registrado, você pode obter esse valor definitivamente consultando os metadados da propriedade de dependência, e, em seguida, usando o valor padrão para definir localmente a propriedade com uma chamada a SetValue.

Contribuições da comunidade

ADICIONAR
A Microsoft está realizando uma pesquisa online para saber sua opinião sobre o site do MSDN. Se você optar por participar, a pesquisa online lhe será apresentada quando você sair do site do MSDN.

Deseja participar?
Mostrar:
© 2014 Microsoft