Search code examples
wpfxamldata-bindingcomboboxcontroltemplate

How can I change the Border Corner Radius of my ToggleButton when ToggleButton is checked?


I got a ComboBox which has a Style where a ToggleButton is on top. I gave it a CornerRadius and I want that when I check the ToggleButton and my ComboBox is opening the bottom CornerRadius should change. My ComboBox style:

<Style x:Key="ComboBoxStyle1" TargetType="{x:Type ComboBox}">
    <Setter Property="Foreground" Value="#D4D4E1"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ComboBox}">
                <Grid >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition MaxWidth="18"/>
                    </Grid.ColumnDefinitions>

                    <ToggleButton Name="PART_EditableTextBox"            
                                  Style="{StaticResource MyButton}"                  
                                  IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                             Padding="5,0,0,0" BorderThickness="0"
                             Height="{TemplateBinding Height}">
                        <ToggleButton.Resources>
                            <Style TargetType="{x:Type Border}">
                                <Setter Property="CornerRadius" Value="10 0 0 10"/>
                            </Style>
                        </ToggleButton.Resources>
                    </ToggleButton>

                    <ToggleButton Grid.Column="1" Margin="0" Background="#2C2F33"
                                 Height="{TemplateBinding Height}" Style="{StaticResource MyButton}"
                                 Focusable="False" BorderThickness="0" 
                                 IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                                 ClickMode="Press">
                        <Path Grid.Column="1" 
                              HorizontalAlignment="Center"
                              VerticalAlignment="Center" 
                              Data="M 0 0 L 4 4 L 8 0 Z"
                              Fill="LightBlue" />
                        <ToggleButton.Resources>
                            <Style TargetType="{x:Type Border}">
                                <Setter Property="CornerRadius" Value="0 10 10 0"/>
                            </Style>
                        </ToggleButton.Resources>
                    </ToggleButton>
                    <ContentPresenter Name="ContentSite"
                                  Content="{TemplateBinding SelectionBoxItem}"
                                  ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                                  ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                                  VerticalAlignment="Center"
                                  HorizontalAlignment="Left"
                                  Margin="5,0,0,0"/>
                    <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"
                                BorderThickness="0" 
                                CornerRadius="0 0 7 7" 
                                Background="#2E3136"
                                BorderBrush="Black"/>
                            <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
                                <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
                            </ScrollViewer>
                        </Grid>
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

My ToggleButton style:

<Style x:Key="MyButton" TargetType="{x:Type ToggleButton}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="Cursor" Value="Hand" />
    <Setter Property="Background" Value="#2C2F33" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <Border Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Opacity" Value="0.8" />
                    </Trigger>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="" Property="" Value="0.8" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

It looks like this when the ComboBox is closed:

Closed ComboBox with all rounded corners.

It looks like this when it is open:

Open ComboBox with all rounded corners and its popup with rounded corners only at the bottom and sharp corners at the top.

However, I am not able to change the bottom CornerRadius to get this type of look like Google:

Open ComboBox with rounded corners only at the top and at the bottom of its popup. The area between the ComboBox and the Popup looks contiguous.


Solution

  • You can add DataTriggers to your ToggleButton styles that change the CornerRadius depending on the IsDropDownOpen property of the ComboBox, which indicates if the Popup is shown.

    <DataTrigger Binding="{Binding IsDropDownOpen, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="True">
       <Setter Property="CornerRadius" Value="10 0 0 0" />
    </DataTrigger>
    
    <DataTrigger Binding="{Binding IsDropDownOpen, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="True">
       <Setter Property="CornerRadius" Value="0 10 0 0" />
    </DataTrigger>
    

    The RelativeSource is used to refer to the parent ComboBox as source. This is the complete code:

    <Style x:Key="ComboBoxStyle1" TargetType="{x:Type ComboBox}">
        <Setter Property="Foreground" Value="#D4D4E1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBox}">
                    <Grid >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition MaxWidth="18"/>
                        </Grid.ColumnDefinitions>
    
                        <ToggleButton Name="PART_EditableTextBox"            
                                      Style="{StaticResource MyButton}"                  
                                      IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                                 Padding="5,0,0,0" BorderThickness="0"
                                 Height="{TemplateBinding Height}">
                            <ToggleButton.Resources>
                                <Style TargetType="{x:Type Border}">
                                    <Setter Property="CornerRadius" Value="10 0 0 10"/>
                                    <Style.Triggers>
                                       <DataTrigger Binding="{Binding IsDropDownOpen, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="True">
                                          <Setter Property="CornerRadius" Value="10 0 0 0" />
                                       </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </ToggleButton.Resources>
                        </ToggleButton>
    
                        <ToggleButton Grid.Column="1" Margin="0" Background="#2C2F33"
                                     Height="{TemplateBinding Height}" Style="{StaticResource MyButton}"
                                     Focusable="False" BorderThickness="0" 
                                     IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                                     ClickMode="Press">
                            <Path Grid.Column="1" 
                                  HorizontalAlignment="Center"
                                  VerticalAlignment="Center" 
                                  Data="M 0 0 L 4 4 L 8 0 Z"
                                  Fill="LightBlue" />
                            <ToggleButton.Resources>
                                <Style TargetType="{x:Type Border}">
                                    <Setter Property="CornerRadius" Value="0 10 10 0"/>
                                    <Style.Triggers>
                                       <DataTrigger Binding="{Binding IsDropDownOpen, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="True">
                                          <Setter Property="CornerRadius" Value="0 10 0 0" />
                                       </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </ToggleButton.Resources>
                        </ToggleButton>
                        <ContentPresenter Name="ContentSite"
                                      Content="{TemplateBinding SelectionBoxItem}"
                                      ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                                      ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                                      VerticalAlignment="Center"
                                      HorizontalAlignment="Left"
                                      Margin="5,0,0,0"/>
                        <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"
                                    BorderThickness="0" 
                                    CornerRadius="0 0 7 7" 
                                    Background="#2E3136"
                                    BorderBrush="Black"/>
                                <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
                                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
                                </ScrollViewer>
                            </Grid>
                        </Popup>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    The closed and opened state look like this:

    Closed and opened state of the ComboBox with different corner radii.