WPF TemplateBinding vs RelativeSource TemplatedParent

169

Quelle est la différence entre ces 2 fixations:

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

et

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

?

PaN1C_Showt1Me
la source
17
si vous avez besoin de TwoWay Binding, vous devez utiliser la deuxième option
Joachim Kerschbaumer

Réponses:

207

TemplateBinding n'est pas tout à fait la même chose. Les documents MSDN sont souvent rédigés par des personnes qui doivent interroger les SDE monosyllabiques sur les fonctionnalités du logiciel, de sorte que les nuances ne sont pas tout à fait exactes.

Les TemplateBindings sont évalués au moment de la compilation par rapport au type spécifié dans le modèle de contrôle. Cela permet une instanciation beaucoup plus rapide des modèles compilés. Il suffit de fouiller le nom dans une liaison de modèle et vous verrez que le compilateur le marquera.

Le balisage de liaison est résolu au moment de l'exécution. Bien que plus lente à s'exécuter, la liaison résoudra les noms de propriété qui ne sont pas visibles sur le type déclaré par le modèle. En plus lent, je ferai remarquer que son genre de relatif puisque l'opération de liaison prend très peu de CPU de l'application. Si vous utilisiez des modèles de contrôle à grande vitesse, vous le remarquerez peut-être.

En pratique, utilisez le TemplateBinding lorsque vous pouvez mais ne craignez pas le Binding.

Grant BlahaErath
la source
18
Donc, le principal pense à retenir: le temps de compilation vs le temps d'exécution. Le TemplateBinding ne fonctionnera pas si vous essayez de le changer pendant l'exécution. Droite ?
PaN1C_Showt1Me
3
Notez également que l'utilisation de Binding au lieu de TemplateBinding peut avoir des implications sur ce que vous voyez pendant la conception. Dans certaines configurations, les propriétés liées à l'aide de {Binding RelativeSource ...} n'apparaîtront pas dans le concepteur (bien qu'elles s'affichent toujours pendant l'exécution), mais si vous passez à l'utilisation de {TemplateBinding ...}, ces propriétés sont évaluées pendant la conception.
lfalin
Une chose que j'ajouterai au cas où cela aiderait les futurs visiteurs est que, comme TemplateBinding est évalué au moment de la compilation, vous ne pouvez pas utiliser TemplateBinding pour se lier à une propriété jointe définie par l'utilisateur. Dans le cas des propriétés attachées définies par l'utilisateur, vous devez utiliser "{Binding RelativeSource = {RelativeSource TemplatedParent} ...}"
MNB
35

TemplateBinding - Plus limitatif que l'utilisation de la liaison régulière

  • Plus efficace qu'une reliure mais elle a moins de fonctionnalités
  • Fonctionne uniquement dans l'arborescence visuelle d'un ControlTemplate
  • Ne fonctionne pas avec les propriétés sur Freezables
  • Ne fonctionne pas dans le déclencheur d'un ControlTemplate
  • Fournit un raccourci dans la définition des propriétés (pas aussi verbeux), par exemple {TemplateBinding targetProperty}

Reliure régulière - N'a pas les limitations ci-dessus de TemplateBinding

  • Respecte les propriétés parentales
  • Réinitialise les valeurs cibles pour effacer toutes les valeurs explicitement définies
  • Exemple: <Ellipse Fill = "{Binding RelativeSource = {RelativeSource TemplatedParent}, Path = Background}" />
Paul Fischer
la source
22

Encore une chose: les TemplateBindings ne permettent pas la conversion de valeur. Ils ne vous permettent pas de passer un convertisseur et ne convertissent pas automatiquement int en chaîne par exemple (ce qui est normal pour une liaison).

Miroslav Nedyalkov
la source
1
Merci Miroslav, c'était le problème que je rencontrais, le passage à l'utilisation de TemplatedParent a résolu le problème.
MikeKulls le
17

TemplateBinding est un raccourci pour Binding avec TemplatedParent mais il n'expose pas toutes les fonctionnalités de la classe Binding, par exemple vous ne pouvez pas contrôler Binding.Mode à partir de TemplateBinding.

Nir
la source
1

Je pensais que TemplateBinding ne prend pas en charge les types Freezable (qui comprend les objets pinceau). Pour contourner le problème. On peut utiliser TemplatedParent

Yaz
la source