WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
一.前言
申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接。
本文主要内容:
- 下拉选择控件ComboBox的自定义样式及扩展;
- 自定义多选控件MultiComboBox;
二.下拉选择控件ComboBox的自定义样式及扩展
2.1基本样式
先看看基础效果图:
从功能上ComboBox有两种状态:
- 可编辑文本;
- 不可编辑文本。
从XAML的逻辑树结构上看,分为几个部分:
- 显示当前内容的区域;
- 下拉按钮,一般使用ToggleButton;
- 弹出的下拉选项列表,使用Popup作为容器;
样式定义代码:
<!--下拉条目样式-->
<Style TargetType="ComboBoxItem" x:Key="ComboBoxItemStyle">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Height" Value="28" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Grid Background="{TemplateBinding Background}" Margin="0,0.5">
<Border x:Name="ItemBackground" IsHitTestVisible="False" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}" />
<ContentPresenter x:Name="contentPresenter" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="ItemBackground" Property="Background" Value="{StaticResource ItemSelectedBackground}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ItemBackground" Property="Background" Value="{StaticResource ItemMouseOverBackground}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--水印:local:ControlAttachProperty.Watermark-->
<!--Label区域:local:ControlAttachProperty.LabelTemplate ,local:ControlAttachProperty.Label-->
<!--附加内容区域:local:ControlAttachProperty.AttachContent-->
<!--圆角:local:ControlAttachProperty.CornerRadius-->
<!--local:ControlAttachProperty.MouseOverBorderBrush-->
<!--local:ControlAttachProperty.FocusBorderBrush-->
<!--local:ControlAttachProperty.FocusBackground-->
<Style TargetType="{x:Type ComboBox}" x:Key="DefaultComboBox">
<Setter Property="Height" Value="30" />
<Setter Property="Width" Value="200" />
<Setter Property="Foreground" Value="{StaticResource TextForeground}" />
<Setter Property="Background" Value="{StaticResource TextBackground}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
<Setter Property="local:ControlAttachProperty.FocusBackground" Value="{StaticResource FocusBackground}" />
<Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="{StaticResource FocusBorderBrush}" />
<Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="{StaticResource MouseOverBorderBrush}" />
<Setter Property="FontFamily" Value="{StaticResource FontFamily}" />
<Setter Property="FontSize" Value="{StaticResource FontSize}" />
<Setter Property="ItemContainerStyle" Value="{StaticResource ComboBoxItemStyle}" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="MaxDropDownHeight" Value="400" />
<Setter Property="ScrollViewer.CanContentScroll" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid x:Name="PART_Root">
<Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
CornerRadius="{TemplateBinding local:ControlAttachProperty.CornerRadius}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="21" />
</Grid.ColumnDefinitions>
<!--Label区域-->
<ContentControl x:Name="Label" Template="{TemplateBinding local:ControlAttachProperty.LabelTemplate}" IsTabStop="False" IsHitTestVisible="False"
Content="{TemplateBinding local:ControlAttachProperty.Label}" Margin="1,1,0,1"/>
<!--附加内容区域-->
<Border x:Name="PART_AttachContent" Panel.ZIndex="2" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" >
<ContentControl VerticalAlignment="Center" VerticalContentAlignment="Center" Template="{TemplateBinding local:ControlAttachProperty.AttachContent}" />
</Border>
<!--下拉按钮-->
<ToggleButton x:Name="PART_DropDownToggle" IsTabStop="False" Style="{StaticResource ComboToggleButton}"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Grid.Column="1" Grid.ColumnSpan="3" IsEnabled="{Binding Path=IsReadOnly,RelativeSource={RelativeSource TemplatedParent},
Converter={x:Static local:XConverter.TrueToFalseConverter},Mode=OneWay}"
Background="{TemplateBinding local:ControlAttachProperty.FocusBackground}"/>
<!--水印-->
<Border Grid.Column="1">
<TextBlock x:Name="Message" Padding="0" Visibility="Collapsed" Text="{TemplateBinding local:ControlAttachProperty.Watermark}"
Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="{StaticResource WatermarkOpacity}" HorizontalAlignment="Left" TextAlignment="Center"
VerticalAlignment="Center" Margin="5,2,5,2" />
</Border>
<!--主内容区域-->
<Grid Grid.Column="1" x:Name="ContentSite" Margin="2 0 0 0" >
<ContentPresenter x:Name="PART_SelectedItem" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"
HorizontalAlignment="Stretch" Margin="2,0,2,0"
IsHitTestVisible="False" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<!--文本编辑-->
<TextBox x:Name="PART_EditableTextBox" Style="{StaticResource EditableTextBoxStyle}" Visibility="Collapsed"
HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" IsHitTestVisible="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
IsReadOnly="{TemplateBinding IsReadOnly}" FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Text}" FontSize="{TemplateBinding FontSize}" />
</Grid>
</Grid>
<!--弹出下拉控件-->
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="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}}">
<Border x:Name="PopupBorder" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Stretch"
Height="Auto" BorderBrush="{TemplateBinding BorderBrush}"
Background="{StaticResource PopupBackground}">
</Border>
<ScrollViewer x:Name="DropDownScrollViewer" BorderThickness="0" Margin="1">
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<!--触发器-->
<ControlTemplate.Triggers>
<!--1.显示水印-->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
<Setter TargetName="Message" Property="Visibility" Value="Visible" />
</DataTrigger>
<!--编辑模式-->
<Trigger Property="IsEditable" Value="True">
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
<Setter TargetName="PART_SelectedItem" Property="Visibility" Value="Collapsed" />
<Setter TargetName="PART_DropDownToggle" Property="Grid.Column" Value="3" />
<Setter TargetName="PART_DropDownToggle" Property="Grid.ColumnSpan" Value="1" />
<Setter TargetName="PART_DropDownToggle" Property="Background" Value="Transparent" />
<Setter Property="IsTabStop" Value="false" />
<Setter TargetName="PART_DropDownToggle" Property="Focusable" Value="False" />
</Trigger> <Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="PART_Root" Property="Opacity" Value="{StaticResource DisableOpacity}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
如果看过本系列前面的文章,对上面的代码就更容易理解了,为了方便支持水印、Label标签、清除内容功能扩展,在基础样式里加了额外的部分,在xaml中有注释说明。
2.2 Label标签样式
效果图:
在2.1的基础样式上扩展即可:
<!--ComboBox包含附加属性Label的样式 LabelComboBox -->
<Style TargetType="{x:Type ComboBox}" x:Key="LabelComboBox" BasedOn="{StaticResource DefaultComboBox}">
<Setter Property="Width" Value="260"></Setter>
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用示例:
<ComboBox Margin="5" ItemsSource="{StaticResource items}" core:ControlAttachProperty.Label="选择性别"
Style="{StaticResource LabelComboBox}" core:ControlAttachProperty.Watermark="水印" />
<ComboBox Margin="5" IsEditable="True" ItemsSource="{StaticResource items}" core:ControlAttachProperty.Label="选择性别"
Style="{StaticResource LabelComboBox}" core:ControlAttachProperty.Watermark="我收水3333333333333333333333印" />
<ComboBox Margin="5" IsEnabled="False" ItemsSource="{StaticResource items}" core:ControlAttachProperty.Label="选择性别"
Style="{StaticResource LabelComboBox}" SelectedIndex="3" />
2.3 扩展清除选中项/文本按钮样式
效果图:
同样,也是在2.1的基础样式上扩展:
<!--ComboBox包含清除Text按钮的样式 ClearButtonComboBox -->
<Style TargetType="{x:Type ComboBox}" x:Key="ClearButtonComboBox" BasedOn="{StaticResource DefaultComboBox}">
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ComboBox}}}"
IsEnabled="{Binding Path=IsReadOnly,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ComboBox}},
Converter={x:Static local:XConverter.TrueToFalseConverter},Mode=OneWay}"
Margin="1,3,0,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--ComboBox包含附加属性Label,以及ClearText按钮的样式 LabelClearButtonComboBox -->
<Style TargetType="{x:Type ComboBox}" x:Key="LabelClearButtonComboBox" BasedOn="{StaticResource DefaultComboBox}">
<Setter Property="Width" Value="280"></Setter>
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ComboBox}}}"
IsEnabled="{Binding Path=IsReadOnly,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ComboBox}},
Converter={x:Static local:XConverter.TrueToFalseConverter},Mode=OneWay}"
Margin="0,3,0,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用示例:
<ComboBox Margin="5" IsEnabled="False" ItemsSource="{StaticResource items}" core:ControlAttachProperty.Label="选择性别"
Style="{StaticResource LabelClearButtonComboBox}" SelectedIndex="3" />
<ComboBox Margin="5" ItemsSource="{StaticResource items}" core:ControlAttachProperty.Label="选择性别"
Style="{StaticResource ClearButtonComboBox}" core:ControlAttachProperty.Watermark="水印" />
三.自定义多选控件MultiComboBox
实际需求中,经常有多选的要求,基于ComboBox简单的实现了一个多选控件MultiComboBox。效果图:
在功能上,可以满足基本需求,实际功能还不完整的,可以根据自己的需求完善,后台C#代码:
/// <summary>
/// MultiComboBox.xaml 的交互逻辑
/// </summary>
[TemplatePart(Name = "PART_ListBox", Type = typeof(ListBox))]
public partial class MultiComboBox : ComboBox
{
/// <summary>
/// 获取选择项集合
/// </summary>
public IList SelectedItems
{
get { return this._ListBox.SelectedItems; }
} /// <summary>
/// 设置或获取选择项
/// </summary>
public new int SelectedIndex
{
get { return this._ListBox.SelectedIndex; }
set { this._ListBox.SelectedIndex = value; }
} private ListBox _ListBox; public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this._ListBox = Template.FindName("PART_ListBox", this) as ListBox;
this._ListBox.SelectionChanged += _ListBox_SelectionChanged;
} void _ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (var item in this.SelectedItems)
{
sb.Append(item.ToString()).Append(";");
}
this.Text = sb.ToString().TrimEnd(';');
} static MultiComboBox()
{
//OverridesDefaultStyleProperty.OverrideMetadata(typeof(MultiComboBox), new FrameworkPropertyMetadata(typeof(MultiComboBox)));
} public MultiComboBox()
{
ListBox ls = new ListBox();
//ls.SelectedItems
} public void SelectAll()
{
this._ListBox.SelectAll(); } public void UnselectAll()
{
this._ListBox.UnselectAll();
}
}
样式上,也实现了同第二节一样的扩展,包括支持水印、Label标签、清除内容功能扩展,就不做具体介绍了,基础样式代码:
<!--多选项样式-->
<Style x:Key="CheckItemStyle" TargetType="{x:Type ListBoxItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}" >
<Border x:Name="Border" Background="{TemplateBinding Background}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<CheckBox IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}">
<ContentPresenter Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</CheckBox>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<!--<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ItemSelectedBackground}" />
<Setter Property="Foreground" Value="{StaticResource ItemSelectedForeground}" />
</Trigger>-->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ItemMouseOverBackground}" />
<Setter Property="Foreground" Value="{StaticResource ItemMouseOverForeground}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Opacity" Value="{StaticResource DisableOpacity}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--MultiComboBox普通样式-->
<Style x:Key="DefaultMultiComboBox" TargetType="{x:Type local:MultiComboBox}">
<Setter Property="Height" Value="30" />
<Setter Property="Width" Value="200" />
<Setter Property="Foreground" Value="{StaticResource TextForeground}" />
<Setter Property="Background" Value="{StaticResource TextBackground}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
<Setter Property="local:ControlAttachProperty.FocusBackground" Value="{StaticResource FocusBackground}" />
<Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="{StaticResource FocusBorderBrush}" />
<Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="{StaticResource MouseOverBorderBrush}" />
<Setter Property="FontFamily" Value="{StaticResource FontFamily}" />
<Setter Property="FontSize" Value="{StaticResource FontSize}" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="MaxDropDownHeight" Value="400" />
<Setter Property="ScrollViewer.CanContentScroll" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MultiComboBox}">
<Grid x:Name="PART_Root">
<Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" />
<Grid x:Name="PART_InnerGrid" Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="21" />
</Grid.ColumnDefinitions>
<!--Label区域-->
<ContentControl x:Name="Label" Template="{TemplateBinding local:ControlAttachProperty.LabelTemplate}" IsTabStop="False" IsHitTestVisible="False"
Content="{TemplateBinding local:ControlAttachProperty.Label}" Margin="1,1,0,1"/>
<!--附加内容区域-->
<Border x:Name="PART_AttachContent" Panel.ZIndex="2" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" >
<ContentControl VerticalAlignment="Center" VerticalContentAlignment="Center" Template="{TemplateBinding local:ControlAttachProperty.AttachContent}" />
</Border>
<!--下拉按钮-->
<ToggleButton x:Name="PART_DropDownToggle" Panel.ZIndex="1" IsTabStop="False" Style="{StaticResource ComboToggleButton}"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Grid.Column="1" Grid.ColumnSpan="3" IsEnabled="{Binding Path=IsReadOnly,RelativeSource={RelativeSource TemplatedParent},
Converter={x:Static local:XConverter.TrueToFalseConverter},Mode=OneWay}"
Background="{TemplateBinding local:ControlAttachProperty.FocusBackground}"/>
<!--水印-->
<Border Grid.Column="1">
<TextBlock x:Name="Message" Padding="0" Visibility="Collapsed" Text="{TemplateBinding local:ControlAttachProperty.Watermark}"
Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="0.6" HorizontalAlignment="Left" TextAlignment="Center"
VerticalAlignment="Center" Margin="5,2,5,2" />
</Border>
<!--内容区-->
<Grid Grid.Column="1" Margin="2 0 0 0">
<!--文本编辑-->
<TextBox x:Name="PART_EditableTextBox" Style="{StaticResource EditableTextBoxStyle}" FontSize="{TemplateBinding FontSize}"
HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" IsHitTestVisible="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
IsReadOnly="{TemplateBinding IsReadOnly}" FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}"
Text="{Binding Path=Text,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" />
</Grid>
<!--弹出多选列表-->
<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}}">
<Border x:Name="PopupBorder" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Stretch"
Height="Auto" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}"/>
<ListBox x:Name="PART_ListBox" SelectionMode="Multiple" ItemsSource="{Binding ItemsSource,RelativeSource={RelativeSource TemplatedParent}}"
ItemTemplate="{TemplateBinding ItemTemplate}"
MaxHeight="{TemplateBinding MaxDropDownHeight}" ItemContainerStyle="{StaticResource CheckItemStyle}"/>
</Grid>
</Popup>
</Grid>
</Grid>
<!--触发器-->
<ControlTemplate.Triggers>
<!--1.显示水印-->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="">
<Setter TargetName="Message" Property="Visibility" Value="Visible" />
</DataTrigger>
<!--编辑模式-->
<Trigger Property="IsEditable" Value="True">
<Setter TargetName="PART_DropDownToggle" Property="Grid.Column" Value="3" />
<Setter TargetName="PART_DropDownToggle" Property="Grid.ColumnSpan" Value="1" />
<Setter TargetName="PART_DropDownToggle" Property="Background" Value="Transparent" />
<Setter Property="IsTabStop" Value="false" />
<Setter TargetName="PART_DropDownToggle" Property="Focusable" Value="False" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="PART_Root" Property="Opacity" Value="{StaticResource DisableOpacity}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--MultiComboBox包含清除Text按钮的样式 ClearButtonMultiComboBox -->
<Style TargetType="{x:Type local:MultiComboBox}" x:Key="ClearButtonMultiComboBox" BasedOn="{StaticResource DefaultMultiComboBox}">
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:MultiComboBox}}}"
IsEnabled="{Binding Path=IsReadOnly,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:MultiComboBox}},
Converter={x:Static local:XConverter.TrueToFalseConverter},Mode=OneWay}"
Margin="1,3,0,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--MultiComboBox包含附加属性Label的样式 LabelMultiComboBox -->
<Style TargetType="{x:Type local:MultiComboBox}" x:Key="LabelMultiComboBox" BasedOn="{StaticResource DefaultMultiComboBox}">
<Setter Property="Width" Value="260"></Setter>
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--MultiComboBox包含附加属性Label,以及ClearText按钮的样式 LabelClearButtonMultiComboBox -->
<Style TargetType="{x:Type local:MultiComboBox}" x:Key="LabelClearButtonMultiComboBox" BasedOn="{StaticResource DefaultMultiComboBox}">
<Setter Property="Width" Value="280"></Setter>
<Setter Property="local:ControlAttachProperty.LabelTemplate" >
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Width="60" Background="{StaticResource TextLabelBackground}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2" Text="{TemplateBinding Content}"></TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="local:ControlAttachProperty.AttachContent">
<Setter.Value>
<ControlTemplate>
<local:FButton FIcon="" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"
local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:MultiComboBox}}}"
IsEnabled="{Binding Path=IsReadOnly,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:MultiComboBox}},
Converter={x:Static local:XConverter.TrueToFalseConverter},Mode=OneWay}"
Margin="0,3,0,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--默认样式-->
<Style TargetType="{x:Type local:MultiComboBox}" BasedOn="{StaticResource DefaultMultiComboBox}"></Style>
使用实例:
<core:MultiComboBox Width="420" Margin="3" IsEditable="True" ItemsSource="{StaticResource itmes}"
core:ControlAttachProperty.Label="分类:" core:ControlAttachProperty.Watermark="...哈哈" Style="{StaticResource ClearButtonMultiComboBox}"/>
<core:MultiComboBox Width="420" Margin="3" IsEditable="True" ItemsSource="{StaticResource itmes}"
core:ControlAttachProperty.Label="分类:" core:ControlAttachProperty.Watermark="...哈哈" Style="{StaticResource LabelMultiComboBox}"/>
<core:MultiComboBox Width="420" Margin="3" IsEditable="False" ItemsSource="{StaticResource itmes}"
core:ControlAttachProperty.Label="分类:" core:ControlAttachProperty.Watermark="...哈哈" Style="{StaticResource LabelClearButtonMultiComboBox}"/> <core:MultiComboBox Width="420" Margin="3" IsEditable="True" ItemsSource="{StaticResource itmes}" IsReadOnly="True" SelectedIndex="3"
core:ControlAttachProperty.Label="分类:" core:ControlAttachProperty.Watermark="...哈哈" Style="{StaticResource LabelClearButtonMultiComboBox}"/> <core:MultiComboBox Width="420" Margin="3" IsEditable="False" ItemsSource="{StaticResource itmes}" IsEnabled="False"
core:ControlAttachProperty.Label="分类:" core:ControlAttachProperty.Watermark="...哈哈" Style="{StaticResource LabelClearButtonMultiComboBox}"/>
补充:EditableTextBoxStyle及ComboToggleButton样式代码:
<Style TargetType="{x:Type ToggleButton}" x:Key="ComboToggleButton">
<Setter Property="Foreground" Value="{StaticResource TextForeground}" />
<Setter Property="local:ControlAttachProperty.FIconSize" Value="18"/>
<Setter Property="local:ControlAttachProperty.FIconMargin" Value="0,1,3,1"/>
<Setter Property="local:ControlAttachProperty.FIcon" Value=""/>
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid x:Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Background="{TemplateBinding Background}" x:Name="Bg" Grid.ColumnSpan="2" Margin="0,1,1,1"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Opacity="0.3"/>
<TextBlock Grid.Column="1" x:Name="FIcon" FontSize="{Binding Path=(local:ControlAttachProperty.FIconSize),RelativeSource={RelativeSource TemplatedParent}}"
Text="{TemplateBinding local:ControlAttachProperty.FIcon}"
local:ControlAttachProperty.AllowsAnimation="{TemplateBinding IsChecked}"
Foreground="{TemplateBinding Foreground}" Style="{StaticResource FIcon}"
Margin="{TemplateBinding local:ControlAttachProperty.FIconMargin}"/>
</Grid>
<!--z触发器-->
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource MouseOverForeground}" />
<Setter Property="Opacity" TargetName="Bg" Value="0.55" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="{StaticResource PressedForeground}" />
<Setter Property="Opacity" TargetName="Bg" Value="0.6" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="{StaticResource PressedForeground}" />
<Setter Property="Opacity" TargetName="Bg" Value="0.6" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="Grid"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <!--编辑状态文本框样式-->
<Style TargetType="{x:Type TextBox}" x:Key="EditableTextBoxStyle">
<Setter Property="Margin" Value="1"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="MaxLength" Value="2048"/>
<Setter Property="Foreground" Value="{StaticResource TextForeground}"/>
<Setter Property="ContextMenu" Value="{DynamicResource TextBoxContextMenu}" />
<Setter Property="SelectionBrush" Value="{StaticResource TextSelectionBrush}" />
<Setter Property="FontSize" Value="{StaticResource FontSize}"></Setter>
<Setter Property="FontFamily" Value="{StaticResource FontFamily}"></Setter>
<Setter Property="Focusable" Value="True"/>
<Setter Property="CaretBrush" Value="{StaticResource TextForeground}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="SnapsToDevicePixels" Value="True"></Setter>
<Style.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Opacity" Value="{StaticResource ReadonlyOpacity}"></Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="{StaticResource DisableOpacity}"></Setter>
</Trigger>
</Style.Triggers>
</Style>
附录:参考引用
WPF自定义控件与样式(1)-矢量字体图标(iconfont)
WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展
WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式
WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式
WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式
版权所有,文章来源:http://www.cnblogs.com/anding
个人能力有限,本文内容仅供学习、探讨,欢迎指正、交流。
WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox的更多相关文章
- 【转】WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 下拉选择控件ComboBox的自定义样式及扩展: 自定义多选控件Mul ...
- WPF 自定义ComboBox样式,自定义多选控件
原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ...
- WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Che ...
- 【转】WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等 本文主要内容: CheckBox复选框的自定义样式,有两种不同的风格实现: RadioB ...
- WPF自定义控件与样式(2)-自定义按钮FButton
一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 还是先看看效果 ...
- WPF自定义控件与样式(10)-进度控件ProcessBar自定义样
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Pro ...
- WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 自定义 ...
- WPF自定义控件与样式(1)-矢量字体图标(iconfont)
一.图标字体 图标字体在网页开发上运用非常广泛,具体可以网络搜索了解,网页上的运用有很多例子,如Bootstrap.但在C/S程序中使用还不多,字体图标其实就是把矢量图形打包到字体文件里,就像使用一般 ...
- WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享
系列文章目录 WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...
随机推荐
- app快速开发
最近由于工作的原因,公司要开发和系统相应的app, 所以了解了一些这方面的内容.(非原生android IOS 开发) 借用其他网站提供的平台. www.apicloud.com
- IOS和Android支持的音频编解码
1.IOS编码 参考文档地址:https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/Multimedi ...
- Beta版本的贡献率百分比
我真的是服了..刚刚写完最后一次作业,还感叹了一下终于完成了最后的工作,一看群还得发一篇. 贡献率这种东西不是应该默认是100%除以团队人数的吗,有没有搞错啊,这样很容易引起团队不融洽的啊. 0313 ...
- vim : 依赖: vim-common (= 2:7.3.429-2ubuntu2.1) 但是
Ubuntu 12.10 安装vim出错[日期:2013-01-18] 来源:Linux社区 作者:Cubernet [字体:大 中 小] 在Ubuntu 12.10中安装vim时出现了如下提示:正在 ...
- 转:linux coredump调试
1 )如何生成 coredump 文件 ? 登陆 LINUX 服务器,任意位置键入 echo "ulimit -c 1024" >> /etc/profile 退出 L ...
- RHEL6p5下ntfs分区的挂载及自动挂载
No.1: #uname -a //查看你的Linux内核版本的命令 No.2:去http://www.atrpms.net/dist/el5/fuse/下载与内核接近的三个东西 fuse-libs- ...
- html5 localStorage实现表单本地存储
随笔开头,我不得不吐槽,为什么我的随笔每次发布之后,都会在分分钟之内移出首页.好气啊!! 进入正题了,项目中有许多表单输入框要填写,还有一些单选复选框之类的.用户可能在填写了大量的信息之后,不小心刷新 ...
- [转]Oracle VM VirtualBox虚拟机,Ubuntu虚拟机共享文件夹
VirtualBox的菜单里选择"设备" -> "安装增强功能...". "设备" -> "共享文档夹",添 ...
- C++模板&泛型编程
---恢复内容开始--- 一.泛型编程 定义:编写与类型无关的逻辑代码,是代码复用的一种手段.模板是泛型编程的基础 模板分为:函数模板和类模板 函数模板:代表了一个函数家族,该函数与类型无关,在使用时 ...
- Python札记 -- 文件压缩
在日常工作当中免不了要对文件进行压缩,Python标准库里也提供了实现压缩功能的模块. 一.简单的例子 首先了解一下压缩单个文件在Python中怎么实现.竹风建了个测试文件夹zip_text,里面有t ...