Sergey Anisimov
Sergey Anisimov

Reputation: 895

WPF XAML Custom combo-box style as on attached image

I have seen a combo-box in one existing WPF application and want to create similar in my own application. I will provide the screenshot of what I want and a code with the screenshot of what I have now. On the first picture, there is a combo-box when it's regular state and on the second when the popup is opened

combo-box in regular statepopup is opened

There are a few moments that I can't achieve. First is that when the popup is opened - it overlaps a toggle button. Second is the shadow around of popup.

My current XAML Style is huge and I hope someone will go through it and he will suggest me how to edit it to achieve a style which I want:

<ControlTemplate x:Key="ToggleButtonStyle" TargetType="ToggleButton" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="20" />
        </Grid.ColumnDefinitions>
        <Border x:Name="OutsideBorder" Grid.ColumnSpan="2" BorderThickness="0 0 0 3" Panel.ZIndex="2"
                        Width="0" BorderBrush="{StaticResource PrimaryColorBrush}">
        </Border>
        <Border
              x:Name="Border" 
              Grid.ColumnSpan="2"
              CornerRadius="0"
              Background="Transparent"
              BorderBrush="#111111"
              BorderThickness="0 0 0 1" >
        </Border>
        <Path 
              x:Name="Arrow"
              Margin="0 0 4 0"
              Grid.Column="1"     
              Fill="#757575"
              Width="10" Height="6"
              Stretch="Fill"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              Data="M7 10l5 5 5-5z">
        </Path>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="ToggleButton.IsChecked" Value="true">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard Storyboard.TargetName="Container" AccelerationRatio="0.4" DecelerationRatio="0.4">
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="OutsideBorder" Storyboard.TargetProperty="(Border.Width)">
                            <SplineDoubleKeyFrame KeyTime="00:00:0.15" Value="400"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard AccelerationRatio="0.4" DecelerationRatio="0.4">
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="OutsideBorder" Storyboard.TargetProperty="(Border.Width)">
                            <SplineDoubleKeyFrame KeyTime="00:00:0.1" Value="0"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard Storyboard.TargetName="Container" AccelerationRatio="0.4" DecelerationRatio="0.4">
                        <ColorAnimationUsingKeyFrames Storyboard.TargetName="Arrow" Storyboard.TargetProperty="Fill.Color">
                            <SplineColorKeyFrame KeyTime="00:00:0.13" Value="{StaticResource PrimaryColor}"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard AccelerationRatio="0.4" DecelerationRatio="0.4">
                       <ColorAnimationUsingKeyFrames Storyboard.TargetName="Arrow" Storyboard.TargetProperty="Fill.Color">
                            <SplineColorKeyFrame KeyTime="00:00:0.13" Value="#757575"/>
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<Style x:Key="ComboBoxEx" TargetType="ComboBox">
    <Setter Property="IsEditable" Value="False"/>
    <Setter Property="IsTextSearchEnabled" Value="False"/>
    <Setter Property="MaxDropDownHeight" Value="300"/>
    <Setter Property="IsSynchronizedWithCurrentItem" Value="True" />
    <Setter Property="StaysOpenOnEdit" Value="True" />
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="Foreground" Value="#757575"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
                <Grid>
                    <ToggleButton 
                        Name="ToggleButton" 
                        Template="{StaticResource ToggleButtonStyle}" 
                        Grid.Column="2" 
                        Focusable="false"
                        IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
                        ClickMode="Press">
                    </ToggleButton>
                    <ContentPresenter
                        Name="ContentSite"
                        IsHitTestVisible="False" 
                        Content="{TemplateBinding SelectionBoxItem}"
                        ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                        ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                        Margin="3,3,23,3"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Left" />
                    <TextBox x:Name="PART_EditableTextBox"
                        Style="{x:Null}" 
                        Template="{StaticResource ComboBoxTextBox}" 
                        HorizontalAlignment="Left" 
                        VerticalAlignment="Center" 
                        Margin="3,3,23,3"
                        Focusable="True" 
                        Background="Transparent"
                        Visibility="Hidden"
                        IsReadOnly="{TemplateBinding IsReadOnly}"/>
                    <Popup 
                        Name="Popup"
                        Placement="Bottom"
                        IsOpen="{TemplateBinding IsDropDownOpen}"
                        AllowsTransparency="True" 
                        Focusable="False"
                        PopupAnimation="Slide">
                        <Grid 
                            Name="DropDown"
                            SnapsToDevicePixels="True"                
                            MinWidth="{TemplateBinding ActualWidth}"
                            MaxHeight="{TemplateBinding MaxDropDownHeight}">
                            <Border 
                                x:Name="DropDownBorder"
                                Background="Green"/>
                            <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
                                <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
                            </ScrollViewer>
                        </Grid>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasItems" Value="false">
                        <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="Gray"/>
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                    </Trigger>
                    <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
                        <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
                        <Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
                    </Trigger>
                    <Trigger Property="IsEditable" Value="true">
                        <Setter Property="IsTabStop" Value="false"/>
                        <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
                        <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="SelectDocTemplateStyle" TargetType="ComboBox" BasedOn="{StaticResource ComboBoxEx}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
                <Grid>
                    <ToggleButton 
                        Name="ToggleButton" 
                        Template="{StaticResource ToggleButtonStyle}" 
                        Focusable="false"
                        IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
                        ClickMode="Press">
                    </ToggleButton>
                    <ContentPresenter
                        Name="ContentSite"
                        IsHitTestVisible="False" 
                        Content="{TemplateBinding SelectionBoxItem}"
                        ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                        ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                        Margin="6,3,23,3"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Left" />
                    <!-- Text box is not used here -->
                    <TextBox x:Name="PART_EditableTextBox" 
                        HorizontalAlignment="Left" 
                        FlowDirection="LeftToRight"
                        VerticalAlignment="Center" 
                        Margin="6,3,23,3"
                        Focusable="True"
                        Foreground="Purple"
                        CaretBrush="Aqua"
                        FontSize="14"
                        Padding="2"
                        FontFamily="{StaticResource LatoBoldItalic}"
                        BorderThickness="0"
                        Background="Transparent"
                        Visibility="Hidden"
                        IsReadOnly="{TemplateBinding IsReadOnly}"
                        Width="{TemplateBinding Width}"/>
                    <Popup 
                        Name="Popup"
                        Placement="Bottom"
                        IsOpen="{TemplateBinding IsDropDownOpen}"
                        AllowsTransparency="True" 
                        Focusable="False"
                        PopupAnimation="Slide">
                        <Grid 
                          Name="DropDown"
                          SnapsToDevicePixels="True"                
                          MinWidth="{TemplateBinding ActualWidth}"
                          MaxHeight="{TemplateBinding MaxDropDownHeight}">
                            <Border 
                            x:Name="DropDownBorder"
                            Background="#9E9E9E">
                            </Border>
                            <ScrollViewer Margin="0,0" SnapsToDevicePixels="True">
                                <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Local" />
                            </ScrollViewer>
                        </Grid>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasItems" Value="false">
                        <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="Gray"/>
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                    </Trigger>
                    <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
                        <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="0"/>
                        <Setter TargetName="DropDownBorder" Property="Margin" Value="0,0,0,0"/>
                    </Trigger>
                    <Trigger Property="IsEditable" Value="true">
                        <Setter Property="IsTabStop" Value="false"/>
                        <Setter TargetName="PART_EditableTextBox" Property="Visibility"    Value="Visible"/>
                        <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="{x:Type ComboBoxItem}" x:Name="ComboBoxItemStyle" TargetType="{x:Type ComboBoxItem}">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="Foreground" Value="#111111"/>
    <Setter Property="FontFamily" Value="{StaticResource LatoRegular}"/>
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="FlowDirection" Value="LeftToRight"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                <Border Name="Border"
                          Padding="10"
                          Background="#E0E0E0"
                          SnapsToDevicePixels="true">
                    <ContentPresenter />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsHighlighted" Value="true">
                        <Setter TargetName="Border" Property="Background" Value="#BDBDBD"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="#888888"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
    <Border x:Name="PART_ContentHost"  Focusable="False" Background="Red" Width="{TemplateBinding Width}" />
</ControlTemplate>

So, my combo-box looks like this now and it is far away from what I want:

regular state

regular state

popup opened

popup opened

The main questions are:

Upvotes: 1

Views: 1197

Answers (1)

RezaNoei
RezaNoei

Reputation: 1479

There is some Close-Source and Some Open-Source MaterialDesign Library for WPF Developers.

Thanks to #ButchersBoy you can download or even modify whole of this themes:

https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit

You need to work around and read similar codes to see what you need to know.

Upvotes: 1

Related Questions