通过前面几节的学习可以看出:控件模板硬编码了一些细节,如颜色方案。这意味着如果希望在按钮中使用相同的元素组合(Border、Grid、Rectangle和ContentPresenter)并采用相同的方式安排他们,但希望提供不同的颜色方案,就必须创建引用不同画刷资源的控件模板副本。
为了解决上述问题,可将那些需要修改的属性(通常是颜色和字体)从模板中提取出来,通过样式进行设置。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<!-- Resources used by the template. -->
<RadialGradientBrush RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3"
x:Key="HighlightBackground">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Blue" Offset=".4" />
</RadialGradientBrush>
<RadialGradientBrush RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3"
x:Key="PressedBackground">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Blue" Offset="1" />
</RadialGradientBrush>
<SolidColorBrush Color="Blue" x:Key="DefaultBackground"></SolidColorBrush>
<SolidColorBrush Color="Gray" x:Key="DisabledBackground"></SolidColorBrush>
<RadialGradientBrush RadiusX="1" RadiusY="5" GradientOrigin="0.5,0.3"
x:Key="Border">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Blue" Offset="1" />
</RadialGradientBrush>
<!-- The button control template. -->
<ControlTemplate x:Key="GradientButtonTemplate" TargetType="{x:Type Button}">
<Border Name="Border" BorderThickness="2" CornerRadius="2"
Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Rectangle Name="FocusCue" Visibility="Hidden" Stroke="Black"
StrokeThickness="1" StrokeDashArray="1 2" SnapsToDevicePixels="True">
</Rectangle>
<ContentPresenter Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="FocusCue" Property="Visibility"
Value="Visible"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- The style that applies the button control template. -->
<Style x:Key="GradientButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Control.Template"
Value="{StaticResource GradientButtonTemplate}"></Setter>
<Setter Property="BorderBrush"
Value="{StaticResource Border}"></Setter>
<Setter Property="Background"
Value="{StaticResource DefaultBackground}"></Setter>
<Setter Property="TextBlock.Foreground"
Value="White"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background"
Value="{StaticResource HighlightBackground}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background"
Value="{StaticResource PressedBackground}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background"
Value="{StaticResource DisabledBackground}"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
注意:
①在理想情况下,应能在控件模板中保留所有触发器,因为他们代表控件的行为,并使用样式简单设置基本属性。当上面的代码因为想对不同的触发器实现不同的颜色方案,所以只能在样式中设置了触发器。
②如果在控件的模板和样式中都设置了触发器,那么样式触发器具有优先权。
③当使用这个新模版时不用在设置Template属性了,要设置Style属性。
④但上面的代码也有局限性,比如,若想实现不同的颜色方案又需要创建多个样式。为了解决这个问题可以是使用自定义控件,后面第18章会详细讲解。