在WPF的控件样式是有点丑,如果你想改变样式,是不行的,你要重构他才行。或者自定义一个下拉框,也是可以的,WPF控件如下图:
图一
图二是我们重构之后的下拉框,可能还有瑕疵。
图二
如果你想重构下拉框,一定要有自定义视觉树、自定义触发器,然后是样式,你也可以加动画。
可以写在页面,也可以写在资源字典里。
写在资源字典里,要在App.xaml进行合并,下图:
还有一种自定义下拉框,新增一个Window窗口,把Window改为ComboBox。如下图:
如果你在新增Window窗口里面还有一个Grid的代码,如下代码:
<Window x:Class="IO._001"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IO"
mc:Ignorable="d"
Title="_001" Height="300" Width="300">
<Grid>
</Grid>
</Window>
Grid的代码一定要去掉,不然会报错:在使用 ItemsSource 之前,项集合必须为空。如下图:
下拉框重构的资源:资源字典代码
<Style TargetType="TextBlock">
<!--字体颜色-->
<Setter Property="Foreground" Value="#FFFFFDFD"></Setter>
<!--字体大小-->
<Setter Property="FontSize" Value="12"></Setter>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Foreground" Value="#FF28BBEB"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<!--自定义动画资源-->
<ControlTemplate.Resources>
<Storyboard x:Key="FocusedOn">
<!--关键帧动画-->
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="(UIElement.Opacity)">
<!--样条关键帧动画(SplineDoubleKeyFrame)-->
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="FocusedOff">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<!--自定义视觉树-->
<Grid>
<!-- 状态开关按钮(ToggleButton)和开关(Switch)也是由Button派生出来的-->
<ToggleButton x:Name="ToggleButton" Focusable="False" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press">
<ToggleButton.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FF5C84F3" Offset="0.849"/>
<GradientStop Color="#FFF9F6F6" Offset="0.616"/>
<GradientStop Color="White" Offset="0.767"/>
<GradientStop Color="#FF4F4F4F" Offset="1"/>
</LinearGradientBrush>
</ToggleButton.Background>
<ToggleButton.Template>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<!--自定义动画-->
<ControlTemplate.Resources>
<Storyboard x:Key="HoverOn">
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="BtnOver" Storyboard.TargetProperty="Opacity" To="0.8"/>
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="Background_over" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
<Storyboard x:Key="HoverOff">
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="BtnOver" Storyboard.TargetProperty="Opacity" To="0"/>
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="Background_over" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
<Storyboard x:Key="PressedOn">
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="BtnPress" Storyboard.TargetProperty="Opacity" To="0.8"/>
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="Background_press" Storyboard.TargetProperty="Opacity" To="1"/>
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="BtnPress_highlight" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
<Storyboard x:Key="PressedOff">
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="BtnPress" Storyboard.TargetProperty="Opacity" To="0"/>
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="Background_press" Storyboard.TargetProperty="Opacity" To="0"/>
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="BtnPress_highlight" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</ControlTemplate.Resources>
<!--自定义视觉树-->
<Grid>
<!--设置下拉框颜色-->
<Rectangle x:Name="Background" Stroke="White" RadiusX="3" RadiusY="3" IsHitTestVisible="false">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF76B4F7" Offset="0"/>
<GradientStop Color="SkyBlue" Offset="0.5"/>
<GradientStop Color="#FF2A15B6" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
<!--END设置下拉框颜色-->
</Rectangle>
<Rectangle x:Name="Background_over" Stroke="#FFABACAD" RadiusX="3" RadiusY="3" Opacity="0" IsHitTestVisible="False"/>
<Rectangle x:Name="Background_press" Stroke="#FFABABAB" RadiusX="3" RadiusY="3" Opacity="0" IsHitTestVisible="False"/>
<Border x:Name="BtnOver" Width="{TemplateBinding ActualWidth}" BorderBrush="#FFABABAB" BorderThickness="1" CornerRadius="3" Opacity="0" HorizontalAlignment="Right">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF818181" Offset="0"/>
<GradientStop Color="#FF979797" Offset="0.171"/>
<GradientStop Color="#FF858585" Offset="0.5"/>
<GradientStop Color="#FF8F8F8F" Offset="0.51"/>
<GradientStop Color="#FF939393" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<Border x:Name="BtnPress" Width="{TemplateBinding ActualWidth}" BorderBrush="White" BorderThickness="1" CornerRadius="3" Opacity="0" HorizontalAlignment="Right">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA8AAAB" Offset="0"/>
<GradientStop Color="#FFD5D7D8" Offset="0.152"/>
<GradientStop Color="#FFE3E9F0" Offset="0.5"/>
<GradientStop Color="#FFDBDEDF" Offset="0.509"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<Border x:Name="BtnPress_highlight" Margin="1" CornerRadius="2" Opacity="0" HorizontalAlignment="Right">
<Border.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FF919191" Offset="0"/>
<GradientStop Color="#A5CED1D2" Offset="0.088"/>
<GradientStop Color="#0095D9FF" Offset="0.221"/>
<GradientStop Color="#0095D9FF" Offset="0.779"/>
<GradientStop Color="#A5CED1D2" Offset="0.912"/>
<GradientStop Color="#FF919191" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<Border x:Name="BtnOverlay" Margin="1" CornerRadius="2" HorizontalAlignment="Right">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#00FFFFFF"/>
<GradientStop Color="#72FFFFFF" Offset="0.189"/>
<GradientStop Color="#72FFFFFF" Offset="0.5"/>
<GradientStop Color="#00FFFFFF" Offset="0.51"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<Path x:Name="BtnArrow" Margin="0,0,7,0" Width="10" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " HorizontalAlignment="Right" Stretch="Uniform">
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#e6e6e6" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Rectangle x:Name="DisabledVisualElement" Margin="1" Fill="#00FFFFFF" RadiusX="3" RadiusY="3" IsHitTestVisible="false" Visibility="Collapsed"/>
</Grid>
<!--自定义触发器-->
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Trigger.ExitActions>
<!--StaticResource – 静态资源-->
<!--StaticResource仅仅会被应用一次,在第一次需要资源时加载。而且这种引用方式不支持向前加载,所有的资源定义必须在引用之前定义。StaticResource通常用在: ·
设计的APP是将所有的资源放入Page或者App这个级别的Resource Dictionary中的,而且不需要在运行时重新计算—例如只保存一些松散文件,逻辑资源的声明等。 ·
不需要给DependencyObject或者Freezable的对象设置属性。 ·
Resource Dictionary将被编译进DLL. ·
需要给很多的Dependency Property赋值。
将一个资源以Static Resource引用,需要用到Static Resource Markup Extension。 它在已经定义的资源中查询特定key的value为XAML的某个属性赋值。这个查询的行为与load-time查找类似,在当前Page的XAML中或者所有Application的Resources中查找,并在运生成运行时对象。-->
<BeginStoryboard Storyboard="{StaticResource HoverOff}" x:Name="HoverOff_BeginStoryboard"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource HoverOn}"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsChecked" Value="true"/>
<Trigger Property="IsPressed" Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource PressedOff}" x:Name="PressedOff_BeginStoryboard"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource PressedOn}" x:Name="PressedOn_BeginStoryboard"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<!--DynamicResource – 动态资源-->
<!--与Static Resource不同的是,Dynamic Resource可以在程序运行时重新评估/计算资源来生成对应的对象/值,它支持向前引用,只要请求的key在整个应用程序内的任何Resources Dictionary定义过就可以被加载。如果有多个相同的key存在,则最后搜索到的资源为有效。-->
<Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
<Setter Property="Visibility" TargetName="DisabledVisualElement" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
<!--ContentPresenter通常出现在ControlTemplate內,且若不使用ContentPresenter则Content属性就无法正常显示。 -->
<ContentPresenter HorizontalAlignment="Left" Margin="3,3,23,3" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False"/>
<TextBox Visibility="Hidden" HorizontalAlignment="Left" Margin="3,3,23,3" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" Background="Transparent" IsReadOnly="{TemplateBinding IsReadOnly}">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
<Rectangle x:Name="DisabledVisualElement" Fill="#A5FFFFFF" RadiusX="4" RadiusY="4" IsHitTestVisible="false" Visibility="Collapsed"/>
<Rectangle x:Name="FocusVisualElement" Margin="-1" Stroke="White" StrokeThickness="1" RadiusX="4" RadiusY="4" IsHitTestVisible="false" Opacity="0"/>
<!--下拉框下拉样式-->
<Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
<!--下拉框下拉边框样式-->
<Border x:Name="DropDownBorder" Background="White" BorderThickness="1" CornerRadius="1,1,3,3">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="SkyBlue" Offset="0"/>
<GradientStop Color="DodgerBlue" Offset="0.5"/>
</LinearGradientBrush>
</Border.BorderBrush>
<!--END下拉框下拉边框样式-->
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Border>
</Grid>
</Popup>
<!--下拉框下拉样式-->
</Grid>
<!--自定义触发器-->
<ControlTemplate.Triggers>
<!--获取焦点-->
<Trigger Property="IsFocused" Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource FocusedOff}" x:Name="FocusedOff_BeginStoryboard"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FocusedOn}"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="MinHeight" Value="95" TargetName="DropDownBorder"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="SkyBlue"/>
<Setter Property="Visibility" TargetName="DisabledVisualElement" Value="Visible"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="AllowsTransparency" SourceName="Popup" Value="true">
<Setter Property="CornerRadius" Value="4" TargetName="DropDownBorder"/>
<Setter Property="Margin" Value="0,2,0,0" TargetName="DropDownBorder"/>
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox"/>
<Setter Property="Visibility" Value="Hidden" TargetName="ContentSite"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--下拉项-->
<Style TargetType="{x:Type ComboBoxItem}" >
<Setter Property="FontSize" Value="16"/>
<Setter Property="Height" Value="24"/>
<!--下拉样式的大小-->
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<ControlTemplate.Resources>
<Storyboard x:Key="HoverOn">
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="BackgroundGradientOver" Storyboard.TargetProperty="Opacity" To="0.73"/>
</Storyboard>
<Storyboard x:Key="HoverOff">
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="BackgroundGradientOver" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
<Storyboard x:Key="SelectedOn">
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="BackgroundGradientSelected" Storyboard.TargetProperty="Opacity" To="0.84"/>
</Storyboard>
<Storyboard x:Key="SelectedOff">
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="BackgroundGradientSelected" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</ControlTemplate.Resources>
<Grid SnapsToDevicePixels="true" FocusVisualStyle="{x:Null}">
<Rectangle x:Name="BackgroundGradientOver" FocusVisualStyle="{x:Null}" Stroke="#FF6E6E6E" RadiusX="2" RadiusY="2" Opacity="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF8F8F8F" Offset="0.5"/>
<GradientStop Color="#FF787878" Offset="0.5"/>
<GradientStop Color="#FFBBBBBB" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="BackgroundGradientSelected" FocusVisualStyle="{x:Null}" Stroke="#FFBCBEBF" RadiusX="2" RadiusY="2" Opacity="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="SkyBlue" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="BackgroundHighlight" FocusVisualStyle="{x:Null}" Margin="1" Stroke="#A0FFFFFF" RadiusX="1" RadiusY="1"/>
<ContentPresenter FocusVisualStyle="{x:Null}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="contentPresenter" Margin="{TemplateBinding Padding}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource HoverOff}" x:Name="HoverOff_BeginStoryboard"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource HoverOn}" x:Name="HoverOn_BeginStoryboard"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsHighlighted" Value="true"/>
<Trigger Property="Selector.IsSelected" Value="True">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource SelectedOff}" x:Name="SelectedOff_BeginStoryboard1"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource SelectedOn}" x:Name="SelectedOn_BeginStoryboard1"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="Blue"></Setter>
<Setter Property="FontSize" Value="24"/>
<Setter Property="Height" Value="24"/>
</Trigger>
</Style.Triggers>
</Style>