Propriedades de dependência somente leitura (WPF .NET)

Você pode usar propriedades de dependência somente leitura para impedir que valores de propriedade sejam definidos de fora do código. Este artigo discute as propriedades de dependência somente leitura existentes e os cenários e técnicas para criar uma propriedade de dependência somente leitura personalizada.

Importante

A documentação do Guia da Área de Trabalho para .NET 7 e .NET 6 está em construção.

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, é útil se você estiver familiarizado com XAML (Extensible Application Markup Language) e souber como escrever aplicativos WPF.

Propriedades de dependência somente leitura existentes

As propriedades de dependência somente leitura normalmente relatam o estado e não devem ser modificáveis por meio de um public acessador. Por exemplo, a estrutura do Windows Presentation Foundation (WPF) implementa a IsMouseOver propriedade como somente leitura porque seu valor só deve ser determinado pela entrada do mouse. Se IsMouseOver forem permitidas outras entradas, seu valor pode se tornar inconsistente com a entrada do mouse. Embora não seja configurável por meio de um acessador, muitas propriedades de public dependência somente leitura existentes têm valores determinados por várias entradas.

Usos de propriedades de dependência somente leitura

As propriedades de dependência somente leitura não são aplicáveis em vários cenários em que as propriedades de dependência normalmente oferecem uma solução. Cenários não aplicáveis incluem vinculação de dados, aplicação de um estilo a um valor, validação, animação e herança. No entanto, uma propriedade de dependência somente leitura pode ser usada como um gatilho de propriedade em um estilo. Por exemplo, IsMouseOver é comumente usado para disparar alterações no plano de fundo, primeiro plano ou outra propriedade visível de um controle quando o mouse está sobre ele. O sistema de propriedades WPF detecta e relata alterações nas propriedades de dependência somente leitura, oferecendo suporte à funcionalidade de gatilho de propriedade. As propriedades de dependência somente leitura também são úteis ao implementar uma propriedade de dependência de tipo de coleção em que apenas os elementos da coleção precisam ser graváveis, não o objeto de coleção em si. Para obter mais informações, consulte Propriedades de dependência de tipo de coleção.

Observação

Somente propriedades de dependência, não propriedades regulares de tempo de execução de linguagem comum, podem ser usadas como gatilhos de propriedade em um estilo.

Criando propriedades de dependência somente leitura personalizadas

Antes de criar uma propriedade de dependência somente leitura, verifique os cenários não aplicáveis.

O processo de criação de uma propriedade de dependência somente leitura é em muitos aspectos semelhante à criação de propriedades de dependência de leitura-gravação, com estas distinções:

  • Ao registrar sua propriedade somente leitura, chame RegisterReadOnly em vez de Register.

  • Ao implementar o wrapper de propriedade CLR, verifique se ele não tem um acessador público set .

  • RegisterReadOnly retorna DependencyPropertyKey em vez de DependencyProperty. Armazene o em um membro de DependencyPropertyKey classe não público.

Você pode determinar o valor de sua propriedade de dependência somente leitura usando qualquer lógica escolhida. A maneira recomendada de definir o valor da propriedade, inicialmente ou como parte da lógica de tempo de execução, é usar a sobrecarga de SetValue que aceita um parâmetro do tipo DependencyPropertyKey. O uso SetValue é preferível a contornar o sistema de propriedades e definir o campo de apoio diretamente.

Como e onde você define o valor de uma propriedade de dependência somente leitura em seu aplicativo afetará o nível de acesso atribuído ao membro da classe que armazena o DependencyPropertyKey. Se você definir apenas o valor da propriedade de dentro da classe que registra a propriedade de dependência, poderá usar um private modificador de acesso. Para cenários em que os valores das propriedades de dependência afetam uns aos outros, você pode usar retornos de chamada e CoerceValueCallback emparelhados PropertyChangedCallback para disparar alterações de valor. Para obter mais informações, consulte Metadados da propriedade de dependência.

Se você precisar alterar o valor de uma propriedade de dependência somente leitura de fora da classe que a registra, poderá usar um internal modificador de acesso para o DependencyPropertyKey. Por exemplo, você pode chamar SetValue de um manipulador de eventos no mesmo assembly. O exemplo a seguir define uma classe Aquarium que chama RegisterReadOnly para criar a propriedade FishCountde dependência somente leitura . O DependencyPropertyKey é atribuído a um internal static readonly campo, para que o código no mesmo assembly possa alterar o valor da propriedade de dependência somente leitura.

public class Aquarium : DependencyObject
{
    // Register a dependency property with the specified property name,
    // property type, owner type, and property metadata.
    // Assign DependencyPropertyKey to a nonpublic field.
    internal static readonly DependencyPropertyKey FishCountPropertyKey =
        DependencyProperty.RegisterReadOnly(
          name: "FishCount",
          propertyType: typeof(int),
          ownerType: typeof(Aquarium),
          typeMetadata: new FrameworkPropertyMetadata());

    // Declare a public get accessor.
    public int FishCount =>
        (int)GetValue(FishCountPropertyKey.DependencyProperty);
}
Public Class Aquarium
    Inherits DependencyObject

    ' Register a dependency property with the specified property name,
    ' property type, owner type, And property metadata.
    ' Assign DependencyPropertyKey to a nonpublic field.
    Friend Shared ReadOnly FishCountPropertyKey As DependencyPropertyKey =
        DependencyProperty.RegisterReadOnly(
            name:="FishCount",
            propertyType:=GetType(Integer),
            ownerType:=GetType(Aquarium),
            typeMetadata:=New FrameworkPropertyMetadata())

    ' Declare a public get accessor.
    Public ReadOnly Property FishCount As Integer
        Get
            Return GetValue(FishCountPropertyKey.DependencyProperty)
        End Get
    End Property

End Class

Como o sistema de propriedades WPF não propaga o lado de fora do código, as propriedades de dependência somente leitura têm melhor segurança de gravação do DependencyPropertyKey que as propriedades de dependência de leitura-gravação. Use uma propriedade de dependência somente leitura quando quiser limitar o acesso de gravação àqueles que têm uma referência ao DependencyPropertyKey.

Por outro lado, o identificador de propriedade de dependência para propriedades de dependência de leitura-gravação é acessível por meio do sistema de propriedades, independentemente do modificador de acesso atribuído a ele. Para obter mais informações, consulte Segurança de propriedade de dependência.

Confira também