WPF TemplateBinding vs 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>

?

Ответ 1

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

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

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

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

Ответ 2

TemplateBinding - Больше ограничений, чем использование обычного привязки

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

Обычный Binding - Не имеет ограничений по TemplateBinding

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

Ответ 3

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

Ответ 4

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

Ответ 5

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, который оценивается сразу после первого времени выполнения. Как вы можете заметить на приведенном ниже рисунке, фон и содержимое применяются от кнопки к шаблону управления.

Ответ 6

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