假設想實現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的效果。
同時這樣的一個樣式動不動就會很長,所以有一些效果沒什麼必要的話就應該省略從簡。