WPF⾃定义ComboBox样式和实现带提⽰的ComboBox
WPF ⾃定义ComboBox样式和实现带提⽰的ComboBox
⼀.⾃定义ComboBox样式
效果:
先添加⼀个Styles⽂件夹,在⾥⾯添加⼀个资源字典ComboBox.xaml,代码如下:
<ResourceDictionary xmlns="/winfx/2006/xaml/prentation"
xmlns:x="/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFDemo"
xmlns:controls="clr-namespace:WPFDemo.Controls">
<!--ComboBox-->
<!--ComBoBox项选中背景⾊-->
<SolidColorBrush x:Key="ComboBoxSelectdBackground" Color="#007ACC"/>
<!--ComBoBox项⿏标经过背景⾊-->
<SolidColorBrush x:Key="ComboBoxMouOverBackground" Color="DarkGray"/>
<!--ComBoBox项选中前景⾊-->
<SolidColorBrush x:Key="ComboBoxSelectedForeground" Color="White"/>
<!--ComBoBox项⿏标经过前景⾊-->
<SolidColorBrush x:Key="ComboBoxMouOverForegrond" Color="White"/>
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
<Grid Height="25" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Border Background="White" Grid.ColumnSpan="2" Opacity="0"/>
<Path x:Name="Arrow" Grid.Column="1" Data="M 0 0 6 6 12 0 Z" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None" Fill=" #999"/>
</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>
苹果主页<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="fal"/>
<Condition Property="IsMouOver" Value="true"/>
</MultiTrigger.Conditions>
<Setter TargetName="_borderbg" Property="Background" Value="{StaticResource ComboBoxMouOverBackground}"/>
<Setter TargetName="_txt" Property="Foreground" Value="{StaticResource ComboBoxMouOverForegrond}"/>
</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"/>
<ContentPrenter HorizontalAlignment="Left" Margin="3,3,0,3" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBind ing SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSele ctor}" IsHitTestVisible="Fal"/>
<!--ToggleButton 已数据绑定到 ComboBox 本⾝以切换 IsDropDownOpen-->
<ToggleButton Grid.Column="0" Grid.ColumnSpan="2" Template="{StaticResource ComboBoxToggleButton}" x:Name="ToggleButton" Fo cusable="fal" 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" Focus able="True" Background="Transparent" IsReadOnly="{TemplateBinding IsReadOnly}"/>
<!--Popup 可显⽰ ComboBox 中的项列表。IsOpen 已数据绑定到通过 ComboBoxToggleButton 来切换的 IsDropDownOpen-->
<Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="Fal" AllowsTransparency="Tr ue" 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" CanConte ntScroll="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>
<!--MultiComboBox普通样式-->
<Style TargetType="{x:Type controls: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 controls:MultiComboBox}">
<Grid>
<Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Width="{TemplateBinding Width}" Height="{Templ ateBinding 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="Disab led">
<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 View Name}" IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay,UpdateSourceTrigger=PropertyChange d}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
皮具保养
</ListBox.ItemContainerStyle>
</ListBox>
<!--下拉按钮-->
<ToggleButton x:Name="PART_DropDownToggle" IsTabStop="Fal"
防震减灾手抄报内容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="Fal" StaysOpen="Fal"
IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom"> <Grid Width="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}" MaxHeight="{Binding MaxDropDownHeight, Re lativeSource={RelativeSource TemplatedParent}}">
<ListBox x:Name="PART_ListBox" SelectionMode="Multiple" BorderThickness="1 0 1 1" Background="White" ItemsSource="{Binding It emsSource,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"/>
<Border x:Name="bg" BorderBrush="#eaeaea" BorderThickness="0"/>
<ContentPrenter 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="IsMouOver" Value="true"/>
<Condition Property="IsSelected" Value="fal"/>
</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="Fal">
<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 P ath=ViewName}"/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="tru e">
<Setter TargetName="chk" Property="IsChecked" Value="true"/>
故事童话
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsSelected}" Value="fal ">
<Setter TargetName="chk" Property="IsChecked" Value="true"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
三亚风景</ListBox>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
添加⼀个Controls⽂件夹,⾥⾯添加⼀个类:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
你喜欢吃什么用英语怎么说using System.Windows;
using System.Windows;
using System.Windows.Controls;
namespace WPFDemo.Controls
{
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 ObrvableCollection<MultiCbxBaData> ChekedItems =new ObrvableCollection<MultiCbxBaData>();
/// <summary>
业务培训心得体会/// ListBox竖向列表
/// </summary>
private ListBox _ListBoxV;
/// <summary>
/// ListBox横向列表
/// </summary>
private ListBox _ListBoxH;
public override void OnApplyTemplate()
{
ba.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)
{
MultiCbxBaData bdc = item as MultiCbxBaData;
if(bdc.IsCheck)
{
_ListBoxV.SelectedItems.Add(bdc);
}
}
}
}
private void_ListBoxH_SelectionChanged(object nder, SelectionChangedEventArgs e)
{
foreach(var item in e.RemovedItems)
{
MultiCbxBaData datachk = item as MultiCbxBaData;
for(int i =0; i < _ListBoxV.SelectedItems.Count; i++)
{
MultiCbxBaData datachklist = _ListBoxV.SelectedItems[i]as MultiCbxBaData;
if(datachklist.ID == datachk.ID)
{