<ControlTemplate x:Key="RoundButtonTemplate" TargetType="Button" >
<Grid x:Name="controlLayout">
<Ellipse x:Name="buttonSurface" Fill="LightBlue" />
<Label x:Name="buttonCaption" Content="OK!"
FontSize="20" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="buttonSurface" Property="Fill"
Value="Blue"/>
<Setter TargetName="buttonCaption"
Property="Foreground" Value="Yellow"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="controlLayout"
Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter TargetName="controlLayout"
Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Роль расширения разметки {TemplateBinding}
Проблема с шаблоном элемента управления связана с тем, что каждая кнопка выглядит и содержит тот же самый текст. Следующее обновление разметки не оказывает никакого влияния:
<Button x:Name="myButton" Width="100" Height="100"
Background="Red" Content="Howdy!" Click="myButton_Click"
Template="{StaticResource RoundButtonTemplate}" />
<Button x:Name="myButton2" Width="100" Height="100"
Background="LightGreen" Content="Cancel!"
Template="{StaticResource RoundButtonTemplate}" />
<Button x:Name="myButton3" Width="100" Height="100"
Background="Yellow" Content="Format"
Template="{StaticResource RoundButtonTemplate}" />
Причина в том, что стандартные свойства элемента управления (такие как
BackGround
и
Content
) переопределяются в шаблоне. Чтобы они стали доступными, их потребуется отобразить на связанные свойства в шаблоне. Решить такие проблемы можно за счет использования расширения разметки
{TemplateBinding}
при построении шаблона. Оно позволяет захватывать настройки свойств, которые определены элементом управления, применяющим шаблон, и использовать их при установке значений в самом шаблоне.
Ниже приведена переделанная версия шаблона
RoundButtonTemplate
, в которой расширение разметки
{TemplateBinding}
применяется для отображения свойства
Background
элемента
Button
на свойство
Fill
элемента
Ellipse
; здесь также обеспечивается действительная передача значения
Content
элемента
Button
свойству
Content
элемента
Label
:
<Ellipse x:Name="buttonSurface" Fill="{TemplateBinding Background}"/>
<Label x:Name="buttonCaption" Content="{TemplateBinding Content}"
FontSize="20" FontWeight="Bold" HorizontalAlignment="Center"
VerticalAlignment="Center" />
После такого обновления появляется возможность создания кнопок с разными цветами и текстом. Результат обновления разметки XAML представлен на рис.27.13.
Роль класса ContentPresenter
При проектировании шаблона для отображения текстового значения элемента управления использовался элемент
Label
. Подобно
Button
он поддерживает свойство
Content
. Следовательно, если применяется расширение разметки
{TemplateBinding}
, тогда можно определять элемент
Button
со сложным содержимым, а не только с простой строкой.
Но что, если необходимо передать сложное содержимое члену шаблона, который не имеет свойства
Content
? Когда в шаблоне требуется определить обобщенную
область отображения содержимого, то вместо элемента управления специфического типа (
Label
или
TextBox
) можно использовать класс
ContentPresenter
. Хотя в рассматриваемом примере в этом нет нужды, ниже показана простая разметка, иллюстрирующая способ построения специального шаблона, который применяет класс
ContentPresenter
для отображения значения свойства
Content
элемента управления, использующего шаблон: