Propriedades de dependência do WPF: Por que preciso especificar um tipo de proprietário?
-
22-08-2019 - |
Pergunta
É assim que eu registro um DependencyProperty
:
public static readonly DependencyProperty UserProperty =
DependencyProperty.Register("User", typeof (User),
typeof (NewOnlineUserNotifier));
public User User
{
get
{
return (User)GetValue(UserProperty);
}
set
{
SetValue(UserProperty, value);
}
}
O terceiro parâmetro do DependencyProperty.Register
O método exige que você especifique o tipo de controle em que a propriedade de dependência reside (neste caso, meu controle do usuário é chamado NewOnlineUserNotifier
).
Minha pergunta é, Por que você realmente especifica o tipo de proprietário e o que acontece se você especificar um tipo diferente do proprietário real?
Solução
O tipo que você chama de método de registro não é o proprietário de fato da propriedade; portanto, você não pode especificar um tipo diferente do proprietário real, pois o tipo que você especifica é o proprietário real.
Um exemplo em que isso pode ser útil é quando você cria um controle personalizado que contém outros controles. Anteriormente, com o WinForms, se você tivesse algumas informações extras que eram úteis apenas para esse contêiner, mas pertenciam semanticamente à criança, o melhor que você poderia fazer era colocar essas informações na propriedade "tag" de retenção. Isso removeu a segurança do tipo e você nunca tinha certeza de que outra classe não tentaria armazenar outra coisa na tag. Agora, com as propriedades de dependência do WPF, permitem vincular valores a objetos sem que o próprio objeto precise manter o valor. Um exemplo trivial:
public class ButtonContainer : Control
{
public Button ChildButton { get; set; }
public static readonly DependencyProperty FirstOwnerProperty =
DependencyProperty.Register("FirstOwner", typeof(ButtonContainer),
typeof(Button));
public ButtonContainer()
{
ChildButton = new Button();
ChildButton.SetValue(FirstOwnerProperty, this);
}
}
Agora, o botão possui uma propriedade extra que só faz sentido no contexto do ButtonContainer e só pode ser acessado no contexto do ButtonContainer - como uma tag TypeAfe e encapsulada.
Usando a nova classe da seguinte maneira:
ButtonContainer container1 = new ButtonContainer();
ButtonContainer container2 = new ButtonContainer();
container2.ChildButton = container1.ChildButton;
À medida que o parto é movido de um contêiner para outro, o valor de sua FirstOwnerProperty viaja com ele como se fosse um membro real da classe de botões. O contêiner2 pode ligar para o cherbutton.getValue (FirstOwnerProperty) e descobrir qual o ButtonContainer criou originalmente o botão (por que ele pode querer fazer isso é deixado como um exercício para o leitor ...). Tudo isso é possível sem a necessidade de subclasse o botão a uma especialidade estreita.
Outras dicas
Isso ocorre porque a mesma dependênciaProperty pode ser definida de maneira diferente (com diferentes metadados) para vários tipos
Em poucas palavras, quando você está registrando um DP, está adicionando um objeto (DP) a uma lista anexada a uma classe (proprietário). Esta operação apenas "vive" na classe onde é declarada e muitas vezes não está relacionada a ela.