WPF TemplateBinding vs RelativeSource TemplatedParent

169

Qual é a diferença entre essas 2 ligações:

<ControlTemplate TargetType="{x:Type Button}">
   <Border BorderBrush="{TemplateBinding Property=Background}">
      <ContentPresenter />
   </Border>
</ControlTemplate>

e

<ControlTemplate TargetType="{x:Type Button}">
   <Border BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}">
      <ContentPresenter />
   </Border>
</ControlTemplate>

?

PaN1C_Showt1Me
fonte
17
se precisar TwoWay Encadernação, você tem que usar a segunda opção
Joachim Kerschbaumer

Respostas:

207

TemplateBinding não é exatamente a mesma coisa. Os documentos do MSDN geralmente são escritos por pessoas que precisam testar SDEs monossilábicas sobre recursos de software, de modo que as nuances não estão certas.

TemplateBindings são avaliadas em tempo de compilação com relação ao tipo especificado no modelo de controle. Isso permite uma instanciação muito mais rápida dos modelos compilados. Apenas atrapalhe o nome em uma ligação de modelo e você verá que o compilador o sinalizará.

A marcação de ligação é resolvida no tempo de execução. Embora a execução seja mais lenta, a ligação resolverá os nomes de propriedades que não são visíveis no tipo declarado pelo modelo. Mais devagar, mostrarei que esse tipo de parente já que a operação de ligação ocupa muito pouco da CPU do aplicativo. Se você usasse modelos de controle em alta velocidade, talvez notasse.

Por uma questão de prática, use o TemplateBinding quando puder, mas não tenha medo do Binding.

Grant BlahaErath
fonte
18
Portanto, o principal é lembrar: tempo de compilação versus tempo de execução. O TemplateBinding não funcionará se você tentar mudar durante o tempo de execução. Certo ?
PaN1C_Showt1Me 18/02/10
3
Observe também que o uso de Binding em vez de TemplateBinding pode ter implicações no que você vê durante o Design Time. Em certas configurações, as propriedades vinculadas usando {Binding RelativeSource ...} não aparecerão no designer (embora elas ainda apareçam durante o tempo de execução), mas se você alternar para usar {TemplateBinding ...} essas propriedades serão avaliadas durante o tempo de design.
Lfalin 12/11/2014
Uma coisa que acrescentarei no caso de ajudar futuros visitantes é que, porque o TemplateBinding é avaliado em tempo de compilação, você não pode usar o TemplateBinding para vincular a uma propriedade anexada definida pelo usuário. No caso de propriedades anexadas definidas pelo usuário, você deve usar "{Binding RelativeSource = {RelativeSource TemplatedParent} ...}"
MNB
35

TemplateBinding - Mais limitante do que usar Binding normal

  • Mais eficiente que um Binding, mas tem menos funcionalidade
  • Funciona apenas dentro da árvore visual de um ControlTemplate
  • Não funciona com propriedades no Freezables
  • Não funciona no gatilho de um ControlTemplate
  • Fornece um atalho na configuração de propriedades (não como detalhada), por exemplo, {TemplateBinding targetProperty}

Ligação Regular - Não possui as limitações acima de TemplateBinding

  • Respeita as propriedades dos pais
  • Redefine os valores alvo para limpar quaisquer valores definidos explicitamente
  • Exemplo: <Elipse Fill = "{Ligação RelativeSource = {RelativeSource TemplatedParent}, Caminho = Plano de fundo}" />
Paul Fischer
fonte
22

Mais uma coisa - TemplateBindings não permite a conversão de valor. Eles não permitem que você passe um conversor e não converte automaticamente int para string, por exemplo (o que é normal para uma ligação).

Miroslav Nedyalkov
fonte
1
Obrigado Miroslav, esse foi o problema que eu estava encontrando. A mudança para o TemplatedParent resolveu o problema.
MikeKulls
17

TemplateBinding é uma abreviação de Binding with TemplatedParent, mas não expõe todos os recursos da classe Binding, por exemplo, você não pode controlar Binding.Mode de TemplateBinding.

Nir
fonte
1

Eu pensei que TemplateBinding não suporta tipos Freezable (que incluem objetos de pincel). Para contornar o problema. Pode-se fazer uso do TemplatedParent

Yaz
fonte