WPF ComboBox

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>


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneOnce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值