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>
?
7 ответов
TemplateBinding не совсем то же самое. Документы MSDN часто пишутся людьми, которым приходится тестировать односложные SDE о функциях программного обеспечения, поэтому нюансы не совсем верны.
Привязки TemplateBindings оцениваются во время компиляции по типу, указанному в шаблоне элемента управления. Это позволяет гораздо быстрее создавать скомпилированные шаблоны. Просто возьмите имя в шаблонной привязке, и вы увидите, что компилятор пометит его.
Обязательная разметка разрешается во время выполнения. При более медленном выполнении привязка разрешит имена свойств, которые не видны в типе, объявленном шаблоном. Медленнее, я укажу, что это своего рода относительный, так как операция связывания занимает очень мало процессора процессора. Если вы загружаете шаблоны управления с высокой скоростью, вы можете заметить это.
На практике используйте TemplateBinding, когда можете, но не бойтесь Binding.
TemplateBinding - больше ограничений, чем при использовании обычного Binding
- Более эффективен, чем Binding, но у него меньше функциональности
- Работает только внутри визуального дерева ControlTemplate
- Не работает со свойствами на Freezables
- Не работает в триггере ControlTemplate
- Предоставляет ярлык в настройке свойств (не такой подробный), например, {TemplateBinding targetProperty}
Обычное связывание - не имеет вышеуказанных ограничений TemplateBinding
- Уважает родительские свойства
- Сбрасывает целевые значения, чтобы очистить любые явно установленные значения
- Пример:
Еще одна вещь - TemplateBindings не позволяет конвертировать значения. Они не позволяют вам передавать Converter и, например, автоматически не конвертируют int в строку (что является нормальным для Binding).
TemplateBinding является сокращением для Binding с TemplatedParent, но он не раскрывает всех возможностей класса Binding, например, вы не можете управлять Binding.Mode из TemplateBinding.
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, который оценивается сразу после первого времени выполнения. Как вы можете заметить на рисунке ниже, фон и содержимое применяются из кнопки к шаблону элемента управления.
Я думал, что TemplateBinding не поддерживает Freezable типы (которые включают объекты кисти). Чтобы обойти проблему. Можно использовать TemplatedParent
Они используются аналогичным образом, но у них есть несколько отличий. Вот ссылка на документацию TemplateBinding: http://msdn.microsoft.com/en-us/library/ms742882.aspx