WPF 自定义ComboBox样式
一、ComboBox基本样式
ComboBox有两种状态,可编辑和不可编辑状态。通过设置IsEditable属性可以切换控件状态。
先看基本样式效果:
基本样式代码如下:
- <!--ComboBox-->
- <!--ComBoBox项选中背景色-->
- <SolidColorBrush x:Key="ComboBoxSelectdBackground" Color="#ff8c69"/>
- <!--ComBoBox项鼠标经过背景色-->
- <SolidColorBrush x:Key="ComboBoxMouseOverBackground" Color="#ff3030"/>
- <!--ComBoBox项选中前景色-->
- <SolidColorBrush x:Key="ComboBoxSelectedForeground" Color="White"/>
- <!--ComBoBox项鼠标经过前景色-->
- <SolidColorBrush x:Key="ComboBoxMouseOverForegrond" Color="White"/>
- <Style TargetType="{x:Type ComboBox}">
- <Setter Property="ItemContainerStyle">
- <Setter.Value>
- <Style TargetType="ComboBoxItem">
- <Setter Property="Height" Value="20"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type ComboBoxItem}">
- <Grid Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">
- <Border x:Name="_borderbg" Background="Transparent"/>
- <TextBlock Margin="3 0 3 0" VerticalAlignment="Center" x:Name="_txt" Foreground="#333" Text="{Binding Content,RelativeSource={RelativeSource TemplatedParent}}"/>
- <Border x:Name="_border" Background="White" Opacity="0"/>
- </Grid>
- <ControlTemplate.Triggers>
- <Trigger Property="IsSelected" Value="true">
- <Setter TargetName="_borderbg" Property="Background" Value="{StaticResource ComboBoxSelectdBackground}" />
- <Setter TargetName="_txt" Property="Foreground" Value="{StaticResource ComboBoxSelectedForeground}"/>
- </Trigger>
- <MultiTrigger>
- <MultiTrigger.Conditions>
- <Condition Property="IsSelected" Value="false"/>
- <Condition Property="IsMouseOver" Value="true"/>
- </MultiTrigger.Conditions>
- <Setter TargetName="_borderbg" Property="Background" Value="{StaticResource ComboBoxMouseOverBackground}" />
- <Setter TargetName="_txt" Property="Foreground" Value="{StaticResource ComboBoxMouseOverForegrond}"/>
- </MultiTrigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- </Setter.Value>
- </Setter>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type ComboBox}">
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="0.7*"/>
- <ColumnDefinition Width="0.3*" MaxWidth="30"/>
- </Grid.ColumnDefinitions>
- <Border Grid.Column="0" Grid.ColumnSpan="2" BorderThickness="1" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="1,0,0,1"/>
- <ContentPresenter HorizontalAlignment="Left" Margin="3,3,0,3" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False"/>
- <!--ToggleButton 已数据绑定到 ComboBox 本身以切换 IsDropDownOpen-->
- <ToggleButton Grid.Column="0" Grid.ColumnSpan="2" Template="{StaticResource ComboBoxToggleButton}" x:Name="ToggleButton" Focusable="false" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>
- <!--必须将 TextBox 命名为 PART_EditableTextBox,否则 ComboBox 将无法识别它-->
- <TextBox Visibility="Hidden" BorderThickness="0" Margin="2 0 0 0" x:Name="PART_EditableTextBox" VerticalAlignment="Center" Focusable="True" Background="Transparent" IsReadOnly="{TemplateBinding IsReadOnly}"/>
- <!--Popup 可显示 ComboBox 中的项列表。IsOpen 已数据绑定到通过 ComboBoxToggleButton 来切换的 IsDropDownOpen-->
- <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide">
- <Grid MaxHeight="150" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
- <Border x:Name="DropDownBorder" BorderBrush="#e8e8e8" BorderThickness="1 0 1 1"/>
- <ScrollViewer Margin="1" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">
- <!--StackPanel 用于显示子级,方法是将 IsItemsHost 设置为 True-->
- <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" Background="White"/>
- </ScrollViewer>
- </Grid>
- </Popup>
- </Grid>
- <ControlTemplate.Triggers>
- <Trigger Property="IsEditable" Value="true">
- <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
- </Trigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
引用示例:
- <ComboBox x:Name="combobox" Width="150" Margin="10" IsEditable="False" BorderBrush="#e8e8e8">
- <CheckBox Content="上海" Tag="1"></CheckBox>
- <CheckBox Content="北京" Tag="2"></CheckBox>
- <CheckBox Content="天津" Tag="3"></CheckBox>
- <CheckBox Content="广州" Tag="4"></CheckBox>
- </ComboBox>
二、ComboBox扩展样式(多选控件)
ComBoBox能够单选选择数据,那么能不能实现多选的操作呢,答案是肯定的。这里多选的自定义控件参考了博主“梦里花落知多少”的内容。我对样式做了补充,使其能够更方便的进行移除多选的内容。同时也更好的展示了已选的内容,大家可以根据实际需求做出更好的展示效果。
先看效果:
2.1、添加自定义控件MultiComboBox
- public class MultiComboBox : ComboBox
- {
- static MultiComboBox()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiComboBox), new FrameworkPropertyMetadata(typeof(MultiComboBox)));
- }
- private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- d.SetValue(e.Property, e.NewValue);
- }
- /// <summary>
- /// 选中项列表
- /// </summary>
- public ObservableCollection<MultiCbxBaseData> ChekedItems
- {
- get { return (ObservableCollection<MultiCbxBaseData>)GetValue(ChekedItemsProperty); }
- set { SetValue(ChekedItemsProperty, value); }
- }
- public static readonly DependencyProperty ChekedItemsProperty =
- DependencyProperty.Register("ChekedItems", typeof(ObservableCollection<MultiCbxBaseData>), typeof(MultiComboBox), new PropertyMetadata(new ObservableCollection<MultiCbxBaseData>(), OnPropertyChanged));
- /// <summary>
- /// ListBox竖向列表
- /// </summary>
- private ListBox _ListBoxV;
- /// <summary>
- /// ListBox横向列表
- /// </summary>
- private ListBox _ListBoxH;
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- _ListBoxV = Template.FindName("PART_ListBox", this) as ListBox;
- _ListBoxH = Template.FindName("PART_ListBoxChk", this) as ListBox;
- _ListBoxH.ItemsSource = ChekedItems;
- _ListBoxV.SelectionChanged += _ListBoxV_SelectionChanged;
- _ListBoxH.SelectionChanged += _ListBoxH_SelectionChanged;
- if (ItemsSource != null)
- {
- foreach (var item in ItemsSource)
- {
- MultiCbxBaseData bdc = item as MultiCbxBaseData;
- if (bdc.IsCheck)
- {
- _ListBoxV.SelectedItems.Add(bdc);
- }
- }
- }
- }
- private void _ListBoxH_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- foreach (var item in e.RemovedItems)
- {
- MultiCbxBaseData datachk = item as MultiCbxBaseData;
- for (int i = ; i < _ListBoxV.SelectedItems.Count; i++)
- {
- MultiCbxBaseData datachklist = _ListBoxV.SelectedItems[i] as MultiCbxBaseData;
- if (datachklist.ID == datachk.ID)
- {
- _ListBoxV.SelectedItems.Remove(_ListBoxV.SelectedItems[i]);
- }
- }
- }
- }
- void _ListBoxV_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- foreach (var item in e.AddedItems)
- {
- MultiCbxBaseData datachk = item as MultiCbxBaseData;
- datachk.IsCheck = true;
- if (ChekedItems.IndexOf(datachk) < )
- {
- ChekedItems.Add(datachk);
- }
- }
- foreach (var item in e.RemovedItems)
- {
- MultiCbxBaseData datachk = item as MultiCbxBaseData;
- datachk.IsCheck = false;
- ChekedItems.Remove(datachk);
- }
- }
- public class MultiCbxBaseData
- {
- private int _id;
- /// <summary>
- /// 关联主键
- /// </summary>
- public int ID
- {
- get { return _id; }
- set { _id = value; }
- }
- private string _viewName;
- /// <summary>
- /// 显示名称
- /// </summary>
- public string ViewName
- {
- get { return _viewName; }
- set
- {
- _viewName = value;
- }
- }
- private bool _isCheck;
- /// <summary>
- /// 是否选中
- /// </summary>
- public bool IsCheck
- {
- get { return _isCheck; }
- set { _isCheck = value;}
- }
- }
- }
2.2、定义MultiComboBox控件的样式
- <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
- <Grid Height="25">
- <Border Grid.Column="1" Background="White" Opacity="0" Cursor="Hand"/>
- <Path x:Name="Arrow" Grid.Column="1" Data="M 0 0 6 6 12 0 Z" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None" Fill="#B1B1B1" />
- </Grid>
- <ControlTemplate.Triggers>
- <Trigger Property="IsChecked" Value="true">
- <Setter TargetName="Arrow" Property="RenderTransform">
- <Setter.Value>
- <RotateTransform CenterX="6" CenterY="3" Angle="180"></RotateTransform>
- </Setter.Value>
- </Setter>
- <Setter TargetName="Arrow" Property="Margin" Value="0 0 0 2"/>
- </Trigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- <!--MultiComboBox普通样式-->
- <Style TargetType="{x:Type local:MultiComboBox}">
- <Setter Property="Width" Value="200" />
- <Setter Property="HorizontalContentAlignment" Value="Stretch" />
- <Setter Property="VerticalContentAlignment" Value="Center" />
- <Setter Property="SnapsToDevicePixels" Value="True" />
- <Setter Property="MaxDropDownHeight" Value="400" />
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type local:MultiComboBox}">
- <Grid>
- <Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderBrush="#eaeaea" BorderThickness="1" >
- <Grid x:Name="PART_Root">
- <Grid x:Name="PART_InnerGrid" Margin="0">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="*" />
- <ColumnDefinition Width="0.3*" MaxWidth="30" />
- </Grid.ColumnDefinitions>
- <ListBox x:Name="PART_ListBoxChk" SelectionMode="Multiple" BorderThickness="0" ScrollViewer.VerticalScrollBarVisibility="Disabled">
- <ListBox.ItemsPanel>
- <ItemsPanelTemplate>
- <VirtualizingStackPanel Orientation="Horizontal" VirtualizingStackPanel.IsVirtualizing="True" />
- </ItemsPanelTemplate>
- </ListBox.ItemsPanel>
- <ListBox.ItemContainerStyle>
- <Style TargetType="ListBoxItem">
- <Setter Property="BorderThickness" Value="0"/>
- <Setter Property="IsSelected" Value="True"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="ListBoxItem">
- <CheckBox BorderThickness="0" VerticalAlignment="Center" HorizontalAlignment="Center" Content="{Binding ViewName}" IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- </ListBox.ItemContainerStyle>
- </ListBox>
- <!--下拉按钮-->
- <ToggleButton x:Name="PART_DropDownToggle" IsTabStop="False"
- IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
- Grid.Column="1" Template="{StaticResource ComboBoxToggleButton}" />
- </Grid>
- </Grid>
- </Border>
- <!--弹出多选列表-->
- <Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" StaysOpen="False"
- IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"
- PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
- <Grid Width="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}" MaxHeight="{Binding MaxDropDownHeight, RelativeSource={RelativeSource TemplatedParent}}" >
- <ListBox x:Name="PART_ListBox" SelectionMode="Multiple" BorderThickness="1 0 1 1" Background="White" ItemsSource="{Binding ItemsSource,RelativeSource={RelativeSource TemplatedParent}}"
- MaxHeight="{TemplateBinding MaxDropDownHeight}" BorderBrush="#eaeaea" >
- <ListBox.ItemContainerStyle>
- <Style TargetType="ListBoxItem">
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type ListBoxItem}" >
- <Grid Height="22">
- <Border x:Name="bg" BorderBrush="#eaeaea" BorderThickness="0"/>
- <ContentPresenter x:Name="content" />
- <Border Background="White" Opacity="0"/>
- </Grid>
- <ControlTemplate.Triggers>
- <Trigger Property="IsSelected" Value="True">
- <Setter TargetName="bg" Property="Background" Value="#ADD6FF" />
- </Trigger>
- <MultiTrigger>
- <MultiTrigger.Conditions>
- <Condition Property="IsMouseOver" Value="true" />
- <Condition Property="IsSelected" Value="false"/>
- </MultiTrigger.Conditions>
- <Setter TargetName="bg" Property="Background" Value="#009BDB" />
- <Setter TargetName="bg" Property="Opacity" Value="0.7"/>
- <Setter Property="Foreground" Value="White" />
- </MultiTrigger>
- <Trigger Property="IsEnabled" Value="False">
- <Setter TargetName="bg" Property="Opacity" Value="0.3" />
- <Setter Property="Foreground" Value="Gray" />
- </Trigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- </ListBox.ItemContainerStyle>
- <ListBox.ItemTemplate>
- <DataTemplate>
- <Grid>
- <CheckBox x:Name="chk" Visibility="Hidden" IsChecked="{Binding IsCheck,Mode=TwoWay}" VerticalAlignment="Center"/>
- <CheckBox VerticalAlignment="Center" Foreground="{Binding Foreground,RelativeSource={RelativeSource AncestorType=ListBoxItem}}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected,Mode=TwoWay}" Content="{Binding Path=ViewName}" />
- </Grid>
- <DataTemplate.Triggers>
- <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="true">
- <Setter TargetName="chk" Property="IsChecked" Value="true"/>
- </DataTrigger>
- <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="false">
- <Setter TargetName="chk" Property="IsChecked" Value="false"/>
- </DataTrigger>
- </DataTemplate.Triggers>
- </DataTemplate>
- </ListBox.ItemTemplate>
- </ListBox>
- </Grid>
- </Popup>
- </Grid>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
2.3、引用示例:
- <local:MultiComboBox x:Name="multiCmb" Margin="10" Width="200"/>
2.4、后台代码(初始化绑定数据):
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- MultiComboBoxList = new ObservableCollection<MultiCbxBaseData>()
- {
- new MultiCbxBaseData(){
- ID=,
- ViewName="张三",
- IsCheck=false
- },
- new MultiCbxBaseData(){
- ID=,
- ViewName="李四",
- IsCheck=false
- },
- new MultiCbxBaseData(){
- ID=,
- ViewName="王五",
- IsCheck=false
- },
- new MultiCbxBaseData(){
- ID=,
- ViewName="马六",
- IsCheck=false
- },
- new MultiCbxBaseData(){
- ID=,
- ViewName="赵七",
- IsCheck=false
- },
- };
- this.multiCmb.ItemsSource = MultiComboBoxList;
- }
- private ObservableCollection<MultiCbxBaseData> MultiComboBoxList;
- }
所有代码已经上传到github:https://github.com/cmfGit/WpfDemo.git
WPF 自定义ComboBox样式的更多相关文章
- WPF 自定义ComboBox样式,自定义多选控件
原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ...
- WPF自定义Window样式(2)
1. 引言 在上一篇中,介绍了如何建立自定义窗体.接下来,我们需要考虑将该自定义窗体基类放到类库中去,只有放到类库中,我们才能在其他地方去方便的引用该基类. 2. 创建类库 接上一篇的项目,先添加一个 ...
- WPF自定义Window样式(1)
1. 引言 WPF是制作界面的一大利器.最近在做一个项目,用的就是WPF.既然使用了WPF了,那么理所当然的,需要自定义窗体样式.所使用的代码是在网上查到的,遗憾的是,整理完毕后,再找那篇帖子却怎么也 ...
- WPF 自定义MenuItem样式
原文:WPF 自定义MenuItem样式 一.前言 默认的MenuItem样式比较普通,这次自定义MenuItem的样式也只是对MenuItem的颜色风格进行变化.需要其他功能的变化,大家可以根据样式 ...
- WPF自定义TabControl样式
WPF自定义TabControl,TabControl美化 XAML代码: <TabControl x:Class="SunCreate.Common.Controls.TabCont ...
- WPF 自定义滚动条样式
先看一下效果: 先分析一下滚动条有哪儿几部分组成: 滚动条总共有五部分组成: 两端的箭头按钮,实际类型为RepeatButton Thumb 两端的空白,实际也是RepeatButton 最后就是Th ...
- WPF 自定义CheckBox样式
自定义CheckBox样式,mark一下,方便以后参考复用 设计介绍: 1.一般CheckBox模板太难看了,肯定要重写其中的模板 2.模板状态为未选中状态和选中状态,设置为默认未选中就好了. 默认状 ...
- WPF 自定义Calendar样式(日历样式,周六周日红色显示)
一.WPF日历控件基本样式 通过Blend获取到Calendar需要设置的三个样式CalendarStyle.CalendarButtonStyle.CalendarDayButtonStyle.Ca ...
- WPF:自定义Metro样式文件夹选择对话框FolderBrowserDialog
1.前言 WPF并没有文件选择对话框,要用也就只有使用Winform版的控件.至今我也没有寻找到一个WPF版本的文件选择对话框. 可能是我眼浊,如果各位知道有功能比较健全的WPF版文件选择对话框.文件 ...
随机推荐
- js改变盒子大小(上下左右)分析
js改变盒子大小 知识点 三个mouse事件:mousedown mousemove mouseup css的定位和cursor 思路 先解决单边问题识别范围,得到所选区域 event. 根据距离,判 ...
- python之hasattr()、 getattr() 、setattr() 函数
这三个方法可以实现反射和内省机制,在实际项目中很常用,功能也很强大. [转]http://www.cnblogs.com/cenyu/p/5713686.html hasattr(object, na ...
- java web(转)
装载:http://www.oschina.net/question/12_52027 OSCHINA 软件库有一个分类——Web框架,该分类中包含多种编程语言的将近500个项目. Web框架是开发者 ...
- Numpy库(个人学习笔记)
一样,咱的计算机还是得先拥有Python,并且安装了Numpy库.有疑问的话可以看这里呦~~~~ 下面开讲: NumPy的主要对象是齐次多维数组.它是一个元素表(通常是数字),并且都是相同类型,由正整 ...
- VISUALSVN: UNABLE TO CONNECT TO A REPOSITORY AT URL 无法连接主机的解决办法
场景:我的系统是win7,安装的 VisualSVN Server 作为svn 服务器,昨天是好的,我手渐,使用鲁大师优化了系统,今天提交,更新的时候,直接提示:Unable to connect t ...
- Python上下文管理器
在Python中让自己创建的函数.类.对象支持with语句,就实现了上线文管理协议.我们经常使用with open(file, "a+") as f:这样的语句,无需手动调用f.c ...
- 一些常用的CSS样式
1. overflow: auto 允许盒子容器内容自动上下滚动 2. style="color:red solid" 设置元素边框样式 3. white-space:nowra ...
- Redis+Restful 构造序列号和压力测试【原创】
[本人原创],欢迎交流和分享技术,转载请附上如下内容:如果你觉得这篇文章对你有帮助,请记得帮我点赞, 谢谢!作者:kevin[转自]http://www.cnblogs.com/itshare/ 很多 ...
- python安装第三方库
在编写爬虫程序时发现unsolved import 一时不解,以为是ide出问题了,其实是没有安装第三方库导致的. 于是到https://pypi.python.org/pypi/requests/去 ...
- new Date的兼容性问题
标准浏览器下正常,结果ie.老版本的IOS微信公众号不支持,搞不懂,原来有兼容性问题 //beginData格式为'yyyy-mm-dd' 1 var _date = new Date(Date.pa ...