2009-07-15 2 views
153

Что такое разница между этими 2 привязок:WPF TemplateBinding против RelativeSource TemplatedParent

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

и

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

?

+15

Если вам нужно связывание с двумя путями, вам нужно использовать второй вариант –

ответ

195

TemplateBinding не совсем то же самое. Документы MSDN часто пишут люди, которым приходится проверять односложные SDE о функциях программного обеспечения, поэтому нюансы не совсем правильные.

TemplateBindings оцениваются во время компиляции по типу, указанному в шаблоне управления. Это позволяет значительно ускорить создание скомпилированных шаблонов. Просто перепутайте имя в шаблоне, и вы увидите, что компилятор отметит его.

Разметка привязки разрешена во время выполнения. При более медленном выполнении привязка будет разрешать имена свойств, которые не видны в типе, объявленном шаблоном. Чем медленнее, тем я буду указывать на то, что его родственник, поскольку операция привязки занимает очень мало процессора приложения. Если бы вы тщательно взламывали шаблоны управления на высокой скорости, вы могли бы заметить это.

Как правило, используйте TemplateBinding, когда можете, но не бойтесь привязки.

+17

Итак, главное помнить: время компиляции и время выполнения. TemplateBinding не будет работать, если вы попытаетесь изменить его во время выполнения. Правильно ? –

+2

Также обратите внимание, что использование привязки вместо TemplateBinding может иметь последствия для того, что вы видите во время разработки. В определенных конфигурациях свойства, связанные с использованием {Binding RelativeSource ...}, не будут отображаться в конструкторе (хотя они все еще отображаются во время выполнения), но если вы переключитесь на использование {TemplateBinding ...}, эти свойства будут оценены во время разработки. – lfalin

15

TemplateBinding является обобщающим для связывания с TemplatedParent но не раскрывает все возможности привязок класса, например, вы не можете контролировать Binding.Mode от TemplateBinding.

1

Я думал, что TemplateBinding не поддерживает типы Freezable (включая объекты кисти). Чтобы обойти проблему. Можно использовать TemplatedParent

18

Еще одна вещь - TemplateBindings не позволяют преобразовывать значение. Они не позволяют вам передавать конвертер и не автоматически конвертировать int в строку, например (что нормально для привязки).

+1

Спасибо Мирослав, это была проблема, с которой я столкнулся, переключение на использование TemplatedParent решило проблему. – MikeKulls

27

TemplateBinding - более жесткие ограничения, чем с помощью регулярного Binding

  • Более эффективным, чем Binding, но она имеет меньше функциональных возможностей
  • только работает в визуальном древовидную ControlTemplate в
  • Не работает со свойствами на Freezables
  • Не работает в Trigger ControlTemplate
  • Предоставляет ярлык в настройке g (не так подробно), например.{TemplateBinding TargetProperty}

Regular Binding - Нет выше ограничений TemplateBinding

  • Уважает Родительские Свойства
  • возвратов Целевые значения, чтобы очистить любые явно установленные значения
  • Пример: < Ellipse Fill = "{Binding RelativeSource = {RelativeSource TemplatedParent}, Path = Background}"/>
2

RelativeSource TemplatedParent

Этот режим позволяет связать данное свойство ControlTemplate к свойству элемента управления ControlTemplate, что применяется. Для того, чтобы хорошо понять проблему здесь пример ниже

<Window.Resources> 
    <ControlTemplate x:Key="template"> 
     <Canvas> 
      <Canvas.RenderTransform> 
       <RotateTransform Angle="20"/> 
      </Canvas.RenderTransform> 
      <Ellipse Height="100" Width="150" 
        Fill="{Binding 
       RelativeSource={RelativeSource TemplatedParent}, 
       Path=Background}"> 

      </Ellipse> 
      <ContentPresenter Margin="35" 
         Content="{Binding RelativeSource={RelativeSource 
         TemplatedParent},Path=Content}"/> 
     </Canvas> 
    </ControlTemplate> 
</Window.Resources> 

<Canvas Name="Parent0"> 
    <Button Margin="50" 
       Template="{StaticResource template}" Height="0" 
       Canvas.Left="0" Canvas.Top="0" Width="0"> 
     <TextBlock FontSize="22">Click me</TextBlock> 
    </Button> 
</Canvas> 

Если я хочу, чтобы применить свойство данного управления, чтобы его шаблон управления, то можно использовать режим TemplatedParent. Существует также аналогичное расширение этой разметки, которое является TemplateBinding, которое является своего рода короткой рукой первого, но TemplateBinding оценивается во время компиляции на контрасте TemplatedParent, который оценивается сразу после первого времени выполнения. Как вы можете заметить на следующем рисунке, фон и контент применяются от кнопки к шаблону управления.