Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O Windows Presentation Foundation (WPF) fornece um conjunto de serviços que podem ser usados para estender a funcionalidade da propriedade de um tipo. Coletivamente, esses serviços são chamados de sistema de propriedades do WPF. Uma propriedade que é apoiada pelo sistema de propriedades do WPF é conhecida como uma propriedade de dependência. Essa visão geral descreve o sistema de propriedades do WPF e os recursos de uma propriedade de dependência, incluindo como usar propriedades de dependência existentes no XAML e no código. Essa visão geral também apresenta aspectos especializados das propriedades de dependência, como metadados de propriedade de dependência e como criar sua própria propriedade de dependência em uma classe personalizada.
Pré-requisitos
Este artigo pressupõe o conhecimento básico do sistema de tipos .NET e da programação orientada a objetos. Para seguir os exemplos neste artigo, ele ajuda a entender o XAML e saber como escrever aplicativos WPF. Para obter mais informações, consulte Tutorial: Criar um novo aplicativo WPF com o .NET.
Propriedades de dependência e propriedades CLR
As propriedades do WPF normalmente são expostas como propriedades padrão do .NET. Você pode interagir com essas propriedades em um nível básico e nunca saber que elas são implementadas como uma propriedade de dependência. No entanto, a familiaridade com alguns ou todos os recursos do sistema de propriedades do WPF ajudará você a aproveitar esses recursos.
A finalidade das propriedades de dependência é fornecer uma maneira de calcular o valor de uma propriedade com base no valor de outras entradas, como:
- Propriedades do sistema, como temas e preferência do usuário.
- Mecanismos de determinação de propriedade em tempo real, como vinculação de dados e animações e storyboards.
- Modelos de uso múltiplo, como recursos e estilos.
- Valores conhecidos por meio de relações pai-filho com outros elementos na árvore de elementos.
Além disso, uma propriedade de dependência pode fornecer:
- Validação autocontida.
- Valores padrão.
- Callbacks que monitoram alterações em outras propriedades.
- Um sistema que pode coagir valores de propriedade com base em informações de runtime.
Classes derivadas podem alterar algumas características de uma propriedade existente substituindo os metadados de uma propriedade de dependência, em vez de substituir a implementação real de propriedades existentes ou criar novas propriedades.
Na referência do SDK, você pode identificar uma propriedade de dependência pela presença de uma seção Informações da Propriedade de Dependência na página de referência gerenciada dessa propriedade. A seção Informações da Propriedade de Dependência inclui um link para o DependencyProperty campo identificador dessa propriedade de dependência. Ele também inclui a lista de opções de metadados para essa propriedade, informações de substituição específicas por classe e outros detalhes.
Propriedades de dependência dão suporte a propriedades CLR
As propriedades de dependência e o sistema de propriedades do WPF expandem a funcionalidade das propriedades, fornecendo um tipo que serve de suporte a uma propriedade, como alternativa ao padrão convencional de associar uma propriedade a um campo privado. O nome desse tipo é DependencyProperty. O outro tipo importante que define o sistema de propriedades do WPF é DependencyObject, que define a classe base que pode registrar e possuir uma propriedade de dependência.
Aqui está uma terminologia comumente usada:
Propriedade de dependência, que é uma propriedade suportada por um DependencyProperty.
Identificador de propriedade de dependência, que é uma instância
DependencyPropertyobtida como valor de retorno ao registrar uma propriedade de dependência e, em seguida, armazenada como um membro estático de uma classe. Muitas das APIs que interagem com o sistema de propriedades do WPF usam o identificador de propriedade de dependência como um parâmetro.CLR "wrapper", que são as implementações
getesetpara a propriedade. Essas implementações incorporam o identificador de propriedade de dependência, usando-o nas chamadas GetValue e SetValue. Dessa forma, o sistema de propriedades do WPF fornece o suporte para a propriedade.
O exemplo a seguir define a IsSpinning propriedade de dependência para mostrar a relação do DependencyProperty identificador com a propriedade que ela suporta.
public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register(
"IsSpinning", typeof(bool),
typeof(MainWindow)
);
public bool IsSpinning
{
get => (bool)GetValue(IsSpinningProperty);
set => SetValue(IsSpinningProperty, value);
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
DependencyProperty.Register("IsSpinning", GetType(Boolean), GetType(MainWindow))
Public Property IsSpinning As Boolean
Get
Return GetValue(IsSpinningProperty)
End Get
Set(value As Boolean)
SetValue(IsSpinningProperty, value)
End Set
End Property
A convenção de nomenclatura da propriedade e seu campo de backup DependencyProperty é importante. O nome do campo é sempre o nome da propriedade, com o sufixo Property acrescentado. Para obter mais informações sobre essa convenção e os motivos para ela, consulte as propriedades de dependência personalizadas.
Definindo valores de propriedade
Você pode definir propriedades no código ou em XAML.
Definindo valores de propriedade em XAML
O exemplo XAML a seguir define a cor da tela de fundo de um botão como vermelho. O valor de string para o atributo XAML é convertido para um tipo WPF pelo analisador XAML do WPF. No código gerado, o tipo WPF é um Color, por meio de um SolidColorBrush.
<Button Content="I am red" Background="Red"/>
O XAML dá suporte a vários formulários de sintaxe para definir propriedades. Qual sintaxe usar para uma propriedade específica depende do tipo de valor usado por uma propriedade e outros fatores, como a presença de um conversor de tipo. Para obter mais informações sobre a sintaxe XAML para definir propriedades, consulte XAML no WPF e Sinaxe XAML em Detalhes
O exemplo XAML a seguir mostra outro plano de fundo de botão que usa a sintaxe do elemento de propriedade em vez de sintaxe de atributo. Em vez de definir uma cor sólida simples, o XAML define a propriedade do botão Background como uma imagem. Um elemento representa essa imagem e um atributo do elemento aninhado especifica a origem da imagem.
<Button Content="I have an image background">
<Button.Background>
<ImageBrush ImageSource="stripes.jpg"/>
</Button.Background>
</Button>
Definindo propriedades no código
Definir valores de propriedade de dependência no código geralmente é apenas uma chamada para a implementação set exposta pelo "wrapper" CLR.
Button myButton = new();
myButton.Width = 200.0;
Dim myButton As New Button With {
.Width = 200.0
}
Obter o valor de uma propriedade é, essencialmente, uma chamada para a implementação do get "empacotador":
double whatWidth = myButton.Width;
Dim whatWidth As Double = myButton.Width
Você também pode chamar as APIs GetValue do sistema de propriedades e SetValue diretamente. Chamar as APIs diretamente é apropriado para alguns cenários, mas geralmente não quando você está usando propriedades existentes. Normalmente, os wrappers são mais convenientes e fornecem melhor visibilidade da propriedade para ferramentas de desenvolvimento.
As propriedades também podem ser definidas em XAML e, em seguida, acessadas posteriormente no código, por meio de code-behind. Para obter detalhes, consulte Code-behind e XAML no WPF
Funcionalidade de propriedade fornecida por uma propriedade de dependência
Ao contrário de uma propriedade que é apoiada por um campo, uma propriedade de dependência estende a funcionalidade de uma propriedade. Muitas vezes, a funcionalidade adicionada representa ou dá suporte a um destes recursos:
Recursos
Você pode definir um valor de propriedade de dependência fazendo referência a um recurso. Os recursos normalmente são especificados como o Resources valor da propriedade de um elemento raiz de página ou do aplicativo, já que esses locais oferecem acesso conveniente ao recurso. Neste exemplo, definimos um SolidColorBrush recurso:
<StackPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</StackPanel.Resources>
Agora que o recurso está definido, podemos referenciar o recurso para fornecer um valor para a Background propriedade:
<Button Background="{DynamicResource MyBrush}" Content="I am gold" />
No WPF XAML, você pode usar uma referência de recurso estático ou dinâmico. Esse recurso específico é referenciado como um DynamicResource
Observação
Os recursos são tratados como um valor local, o que significa que, se você definir outro valor local, eliminará a referência de recurso. Para obter mais informações, consulte Precedência do valor da propriedade Dependency.
Vinculação de dados
Uma propriedade de dependência pode referenciar um valor por meio da associação de dados. A associação de dados funciona por meio de uma sintaxe de extensão de marcação específica no XAML, ou do objeto Binding no código. Com a associação de dados, a determinação do valor final da propriedade é adiada até o tempo de execução, momento em que o valor é obtido de uma fonte de dados.
O exemplo a seguir define a Content propriedade para um Button, usando uma associação declarada em XAML. A associação usa um contexto de dados herdado e uma XmlDataProvider fonte de dados (não mostrado). A associação em si especifica a propriedade de origem dentro da fonte de dados por XPath.
<Button Content="{Binding Source={StaticResource TestData}, XPath=test[1]/@text}"/>
Observação
As associações são tratadas como um valor local, o que significa que, se você definir outro valor local, eliminará a associação. Para obter detalhes, consulte Precedência do valor da propriedade de dependência.
As propriedades de dependência ou a DependencyObject classe não suportam INotifyPropertyChanged nativamente para notificações de mudanças no DependencyObject valor da propriedade de origem em operações de vinculação de dados. Para obter mais informações sobre como criar propriedades para uso na associação de dados que podem relatar alterações em um destino de associação de dados, consulte a visão geral da associação de dados
Estilos
Estilos e modelos são motivos atraentes para usar propriedades de dependência. Estilos são particularmente úteis para definir propriedades que definem a interface do usuário do aplicativo. Os estilos normalmente são definidos como recursos em XAML. Os estilos interagem com o sistema de propriedades porque normalmente contêm "modificadores" para propriedades específicas e "gatilhos" que alteram um valor de propriedade com base no valor do tempo de execução de outra propriedade.
O exemplo a seguir cria um estilo simples, que seria definido dentro de um Resources dicionário (não mostrado). Em seguida, o estilo é aplicado diretamente à propriedade Style de um Button. O setter dentro do estilo define a propriedade Background de um Button estilizado para verde.
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}" Content="I am green"/>
Para obter mais informações, consulte Estilo e modelagem.
Animações
As propriedades de dependência podem ser animadas. Quando uma animação aplicada é executada, o valor animado tem precedência maior do que qualquer outro valor de propriedade, incluindo um valor local.
O exemplo a seguir anima a propriedade Background de um Button. Tecnicamente, a sintaxe do elemento de propriedade estabelece um espaço em branco SolidColorBrush como Background, e a propriedade Color do SolidColorBrush é animada.
<Button Content="I am animated">
<Button.Background>
<SolidColorBrush x:Name="AnimBrush"/>
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimBrush"
Storyboard.TargetProperty="(SolidColorBrush.Color)"
From="Blue" To="White" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Para obter mais informações sobre como animar propriedades, veja Visão geral de animação e Visão geral de Storyboards
Substituições de metadados
Você pode alterar comportamentos específicos de uma propriedade de dependência substituindo seus metadados quando deriva da classe que registrou originalmente a propriedade de dependência. A substituição de metadados depende do identificador DependencyProperty e não exige a reimplementação da propriedade. A alteração de metadados é tratada nativamente pelo sistema de propriedades. Cada classe potencialmente contém metadados individuais para todas as propriedades herdadas de classes base, por tipo.
O exemplo a seguir substitui os metadados de uma DefaultStyleKey propriedade de dependência. Sobrescrever metadados para essa propriedade específica de dependência é parte de um padrão de implementação para criar controles que podem utilizar estilos padrão de temas.
public class SpinnerControl : ItemsControl
{
static SpinnerControl() => DefaultStyleKeyProperty.OverrideMetadata(
typeof(SpinnerControl),
new FrameworkPropertyMetadata(typeof(SpinnerControl))
);
}
Public Class SpinnerControl
Inherits ItemsControl
Shared Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(SpinnerControl), New FrameworkPropertyMetadata(GetType(SpinnerControl)))
End Sub
End Class
Para obter mais informações sobre como substituir ou acessar metadados para propriedades de dependência, consulte Substituir metadados de uma propriedade de dependência.
Herança do valor da propriedade
Um elemento pode herdar o valor de uma propriedade de dependência de seu pai na árvore de objetos.
Observação
O comportamento da herança do valor da propriedade não está habilitado globalmente para todas as propriedades de dependências, pois o tempo necessário para calcular a herança afeta o desempenho. A herança do valor da propriedade normalmente só é habilitada em cenários que sugerem aplicabilidade. Você pode verificar se uma propriedade de dependência herda examinando a seção Informações da Propriedade de Dependência para essa propriedade de dependência na referência do SDK.
O exemplo a seguir mostra uma associação que inclui a DataContext propriedade para especificar a origem da associação. Assim, as associações em objetos filho não precisam especificar a fonte e podem usar o valor herdado do objeto pai DataContextStackPanel. Ou, um objeto filho pode especificar diretamente DataContext ou um Source no Binding, e não usar o valor herdado.
<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource TestData}}">
<Button Content="{Binding XPath=test[2]/@text}"/>
</StackPanel>
Para obter mais informações, consulte Herança do valor da propriedade.
Integração de designer do WPF
Controles personalizados com propriedades implementadas como propriedades de dependência integram-se bem ao Designer do WPF para Visual Studio. Um exemplo é a capacidade de editar propriedades de dependência diretas e anexadas na janela Propriedades . Para obter mais informações, consulte a visão geral da criação de controle
Precedência do valor da propriedade de dependência
Qualquer uma das entradas baseadas em propriedade dentro do sistema de propriedades do WPF pode definir o valor de uma propriedade de dependência. A precedência do valor da propriedade de dependência existe para que os vários cenários de como as propriedades obtenham seus valores interajam de maneira previsível.
Observação
Às vezes, a documentação do SDK usa o termo "valor local" ou "valor definido localmente" ao discutir as propriedades de dependência. Um valor definido localmente é um valor de propriedade definido diretamente em uma instância de objeto no código ou como um atributo de elemento em XAML.
O exemplo a seguir inclui um estilo que se aplica à Background propriedade de qualquer botão, mas especifica um botão com uma propriedade definida Background localmente. Tecnicamente, esse botão tem sua Background propriedade definida duas vezes, embora apenas um valor se aplique: o valor com a precedência mais alta. Um valor definido localmente tem a precedência mais alta, exceto uma animação em execução, que não existe aqui. Portanto, o segundo botão usa o valor definido localmente da propriedade Background, em vez do valor de configuração de estilo. O primeiro botão não tem nenhum valor local ou outro valor com precedência maior que um setter de estilo e, portanto, usa o valor de setter de estilo para a propriedade Background.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Orange"/>
</Style>
</StackPanel.Resources>
<Button>I am styled orange</Button>
<Button Background="Pink">I am locally set to pink (not styled orange)</Button>
</StackPanel>
Por que existe a precedência da propriedade de dependência?
Os valores definidos localmente têm precedência sobre valores de setter de estilo, que dão suporte ao controle local das propriedades do elemento. Para obter detalhes, consulte Precedência do valor da propriedade de dependência.
Observação
Várias propriedades definidas em elementos do WPF não são propriedades de dependência, pois as propriedades de dependência geralmente eram implementadas somente quando um recurso do sistema de propriedades do WPF era necessário. Os recursos incluem associação de dados, estilo, animação, suporte a valor padrão, herança, propriedades anexadas e invalidação.
Saiba mais sobre as propriedades de dependência
Desenvolvedores de componentes ou desenvolvedores de aplicativos podem querer criar sua própria propriedade de dependência para adicionar recursos, como suporte a associação de dados ou estilos, ou suporte a invalidação e coerção de valor. Para obter mais informações, consulte Propriedades de dependência personalizadas.
Considere as propriedades de dependência como propriedades públicas, acessíveis ou detectáveis por qualquer chamador com acesso a uma instância. Para obter mais informações, consulte segurança da propriedade de dependência.
Uma propriedade anexada é um tipo de propriedade que dá suporte a uma sintaxe especializada em XAML. Uma propriedade anexada geralmente não tem uma correspondência 1:1 com uma propriedade common language runtime e não é necessariamente uma propriedade de dependência. A principal finalidade de uma propriedade anexada é permitir que elementos filho relatem valores de propriedade a um elemento pai, mesmo que o elemento pai e o elemento filho não incluam essa propriedade como parte das listagens de membros da classe. Um cenário principal é permitir que um elemento filho informe aos elementos pai como eles devem ser apresentados na interface do usuário. Para obter exemplos, consulte Dock e Left. Para obter mais informações, consulte a visão geral das propriedades anexadas.
Consulte também
.NET Desktop feedback