WPF之下拉框的重构和自定义

在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>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值