ScrollViewer样式参考http://blog.csdn.net/oneonce/article/details/77160487
效果
Sytle
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrls="clr-namespace:ImageButtonTest01.Control"
xmlns:converter="clr-namespace:ImageButtonTest01.Control.Converter">
<converter:BoolToVisibility x:Key="BTV"/>
<converter:PlaceholderFontSizeConverter x:Key="PHFSC"/>
<converter:ImageTextBoxMarginLeftConverter x:Key="ITBMLC"/>
<converter:BoolOppositeConverter x:Key="BOC"/>
<SolidColorBrush x:Key="ComboToggleButton.MouseMove.Foreground" Color="#FF7AC0EE"/>
<SolidColorBrush x:Key="ComboToggleButton.Checked.Foreground" Color="#801AC0EE"/>
<Style x:Key="ComboToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="txt" Grid.Column="1" RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Center" VerticalAlignment="Center"
FontFamily="/ImageButtonTest01;component/Resources/#iconfont"
Text=""
Foreground="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}">
<TextBlock.RenderTransform>
<RotateTransform x:Name="transIcon" Angle="0"/>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="true"></Condition>
</MultiTrigger.Conditions>
<Setter TargetName="txt" Property="Foreground" Value="{StaticResource ComboToggleButton.Checked.Foreground}"/>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="transIcon" Storyboard.TargetProperty="Angle" To="180" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="transIcon" Storyboard.TargetProperty="Angle" To="0" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="txt" Property="Foreground" Value="{StaticResource ComboToggleButton.MouseMove.Foreground}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="EditableTextBoxStyle" TargetType="{x:Type TextBox}">
<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="Black"/>
<Setter Property="ContextMenu" Value="{DynamicResource TextBoxContextMenu}"/>
<Setter Property="SelectionBrush" Value="Bisque"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Focusable" Value="True"/>
<Setter Property="CaretBrush" Value="Black"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Style.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Opacity" Value="0.8"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</Style.Triggers>
</Style>
<SolidColorBrush x:Key="PlaceholderComboBox.Static.BorderBrush" Color="#FF909090"/>
<SolidColorBrush x:Key="PlaceholderComboBox.Static.Foreground" Color="#FFAAAAAA"/>
<SolidColorBrush x:Key="PlaceholderComboBox.Focused.BorderBrush" Color="#FF007ACC"/>
<SolidColorBrush x:Key="PlaceholderComboBox.MouseOver.BorderBrush" Color="#FF1E1E1E"/>
<ControlTemplate x:Key="placeholderComboBoxTemplate" TargetType="{x:Type ctrls:PlaceholderComboBox}">
<Border x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{StaticResource PlaceholderComboBox.Static.BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<!--左圆角-->
<ColumnDefinition Width="{Binding CornerRadius.TopLeft, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ITBMLC}, ConverterParameter=0.4}"/>
<!--内容显示-->
<ColumnDefinition Width="*"/>
<!--清除按钮-->
<ColumnDefinition Width="Auto"/>
<!--下拉按钮-->
<ColumnDefinition Width="Auto"/>
<!--右圆角-->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="PART_Placeholder" Grid.Column="1" Margin="3,0,0,0"
IsHitTestVisible="False"
HorizontalAlignment="Left" VerticalAlignment="Center"
SnapsToDevicePixels="True"
Visibility="Collapsed" Opacity="0.6"
TextAlignment="Left"
Text="{Binding Path=PlaceHolder, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
FontSize="{Binding FontSize, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource PHFSC}}"/>
<ctrls:ImageButton x:Name="PART_ClearButton" Grid.Column="2"
Margin="2" IsTabStop="False" IsEnabled="True"
FontFamily="/ImageButtonTest01;component/Resources/#iconfont" FontSize="20"
Content=""
HorizontalAlignment="Right"
VerticalAlignment="Center"
Style="{StaticResource ImageButtonTransparent}"
Visibility="{Binding ShowClearButton,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BTV}}"/>
<Grid Grid.Column="1" x:Name="ContentSite">
<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" IsHitTestVisible="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="Stretch" VerticalAlignment="Center"
HorizontalContentAlignment="Left" TextAlignment="Left"
IsReadOnly="{TemplateBinding IsReadOnly}"
FontFamily="{TemplateBinding FontFamily}"
Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Text}"
FontSize="{TemplateBinding FontSize}"/>
</Grid>
<ToggleButton x:Name="PART_DropDownToggle" Grid.Column="1" Grid.ColumnSpan="3"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{Binding Background,RelativeSource={RelativeSource TemplatedParent}}"
Foreground="Black" FontWeight="Medium"
IsEnabled="{Binding Path=IsReadOnly,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay, Converter={StaticResource BOC}}"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ComboToggleButtonStyle}">
<ToggleButton.RenderTransform>
<RotateTransform x:Name="transIcon" Angle="0"/>
</ToggleButton.RenderTransform>
</ToggleButton>
<!--弹出下拉控件-->
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False"
IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}"
Placement="Bottom">
<Grid Background="#FFFFFFFF"
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="Transparent">
</Border>
<ScrollViewer x:Name="DropDownScrollViewer"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
Style="{StaticResource scrollviewerDefaultStyle}">
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="">
<Setter TargetName="PART_Placeholder" Property="Visibility" Value="Visible" />
<Setter TargetName="PART_ClearButton" Property="IsEnabled" Value="False" />
</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="Background" Value="Transparent"/>
<Setter TargetName="PART_DropDownToggle" Property="Grid.Column" Value="3"/>
<Setter TargetName="PART_DropDownToggle" Property="Grid.ColumnSpan" Value="1"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter TargetName="PART_DropDownToggle" Property="Focusable" Value="False"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="{StaticResource PlaceholderComboBox.MouseOver.BorderBrush}"/>
<Setter TargetName="PART_DropDownToggle" Property="Foreground" Value="{StaticResource PlaceholderComboBox.MouseOver.BorderBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="red"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="{StaticResource PlaceholderComboBox.Focused.BorderBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="border" Property="Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsStylusCaptured" Value="True">
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type ctrls:PlaceholderComboBox}">
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Background" Value="WhiteSmoke"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="BorderBrush" Value="{StaticResource ImageTextBox.Static.BorderBrush}"/>
<Setter Property="Template" Value="{StaticResource placeholderComboBoxTemplate}"/>
</Style>
</ResourceDictionary>
CS:
public class PlaceholderComboBox : ComboBox
{
private ImageButton mClearTextButton;
static PlaceholderComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PlaceholderComboBox), new FrameworkPropertyMetadata(typeof(PlaceholderComboBox)));
}
public PlaceholderComboBox()
{
}
public override void OnApplyTemplate()
{
mClearTextButton = GetTemplateChild("PART_ClearButton") as ImageButton;
if (null != mClearTextButton)
{
mClearTextButton.Click += OnClearTextButtonClick;
}
base.OnApplyTemplate();
}
private void OnClearTextButtonClick(object sender, RoutedEventArgs e)
{
Text = "";
}
public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register(nameof(ShowClearButton), typeof(bool),
typeof(PlaceholderComboBox), new PropertyMetadata(true));
public bool ShowClearButton
{
get { return (bool)GetValue(ShowClearButtonProperty); }
set { SetValue(ShowClearButtonProperty, value); }
}
public static readonly DependencyProperty PlaceHolderProperty = DependencyProperty.Register(nameof(PlaceHolder), typeof(string),
typeof(PlaceholderComboBox), new PropertyMetadata("Placeholder"));
public string PlaceHolder
{
get { return (string)GetValue(PlaceHolderProperty); }
set { SetValue(PlaceHolderProperty, value); }
}
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(nameof(CornerRadius), typeof(CornerRadius),
typeof(PlaceholderComboBox), new PropertyMetadata(new CornerRadius(0, 0, 0, 0)));
public CornerRadius CornerRadius
{
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
}
converter:
public class BoolOppositeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (null == value)
{
return false;
}
bool bv = (bool)value;
return !bv;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class PlaceholderFontSizeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double v = (double)value;
return (v * 3.5) / 5.0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class ImageTextBoxMarginLeftConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double)
{
double v = (double)value;
if (null != parameter)
{
return v * double.Parse(parameter.ToString());
}
return v * 2.0 / 5.0;
}
return 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class BoolOppositeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (null == value)
{
return false;
}
bool bv = (bool)value;
return !bv;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<control:PlaceholderComboBox Width="300" Height="45" FontSize="30"
ShowClearButton="False"
PlaceHolder="请选择/输入"
IsEditable="False"
CornerRadius="0">
<ComboBoxItem>11111111111</ComboBoxItem>
<ComboBoxItem>22222222222</ComboBoxItem>
<ComboBoxItem>3333333333333</ComboBoxItem>
<ComboBoxItem>4444444444444444444444444</ComboBoxItem>
</control:PlaceholderComboBox>
<control:PlaceholderComboBox Width="300" Height="45" FontSize="30" Margin="5"
ShowClearButton="True"
PlaceHolder="请选择/输入"
IsEditable="True"
CornerRadius="0">
<ComboBoxItem>aaaaaaaaaaaaa</ComboBoxItem>
<ComboBoxItem>bbbbbbbbbbbbbb</ComboBoxItem>
<ComboBoxItem>ccccccc</ComboBoxItem>
<ComboBoxItem>ddddddddddddddddd</ComboBoxItem>
</control:PlaceholderComboBox>