假设想实现ComboBoxItem的Foreground样式,可以在PointerOver或Pressed的状态下呈现不同的效果,那么可以这样实现:
<Style x:Name="DelayClockComboBoxStyle" TargetType="ComboBox">
<Setter Property="Height" Value="48"/>
<Setter Property="Width" Value="180"/>
<Setter Property="TabNavigation" Value="Once" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}" />
<Setter Property="ComboBox.ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border Width="180" Height="48" Background="Transparent" Margin="0"
BorderThickness="2" BorderBrush="White">
<!--Foreground直接绑定本身所在的容器ContentPresenter-->
<TextBlock Text="{Binding}" FontSize="26" Foreground="{Binding Foreground, ElementName=ContentPresenter}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<!--Pressed时改变ContentPresendter的Foreground,那么item的foreground也跟着改变-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppAccentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Background"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="White" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="FocusedPressed"/>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
<VisualState x:Name="FocusedDropDown">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PopupBorder"
Storyboard.TargetProperty="Visibility"
Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DropDownStates">
<VisualState x:Name="Opened">
<Storyboard>
<SplitOpenThemeAnimation
OpenedTargetName="PopupBorder"
ContentTargetName="ScrollViewer"
ClosedTargetName="ContentPresenter"
ContentTranslationOffset="0"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"
ClosedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownClosedHeight}" />
</Storyboard>
</VisualState>
<VisualState x:Name="Closed">
<Storyboard>
<SplitCloseThemeAnimation
OpenedTargetName="PopupBorder"
ContentTargetName="ScrollViewer"
ClosedTargetName="ContentPresenter"
ContentTranslationOffset="40"
OffsetFromCenter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOffset}"
ContentTranslationDirection="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.SelectedItemDirection}"
OpenedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownOpenedHeight}"
ClosedLength="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DropDownClosedHeight}" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background"
Background="Transparent"
BorderThickness="0"/>
<!--此处的ContentPresendter对应着ItemTemplate中的每一个Item-->
<ContentPresenter x:Name="ContentPresenter"
Margin="{TemplateBinding Padding}"
Foreground="White"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<Popup x:Name="Popup">
<Border x:Name="PopupBorder"
Background="Transparent"
BorderThickness="3"
BorderBrush="White"
HorizontalAlignment="Stretch">
<ScrollViewer x:Name="ScrollViewer"
Foreground="{StaticResource ComboBoxPopupForegroundThemeBrush}"
VerticalSnapPointsType="OptionalSingle"
VerticalSnapPointsAlignment="Far"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}"
ZoomMode="Disabled">
<ItemsPresenter/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
VisualStateGroup中的每一个VisualState与先后顺序有关的,有可能后一个State会覆盖了前一个State的效果。
同时这样的一个样式动不动就会很长,所以有一些效果没什么必要的话就应该省略从简。