Search code examples
c#wpfcomboboxdatagriddatagridcomboboxcolumn

How to hide the ComboBox's drop-down on click on one of its ComboBoxItem-s when the ComboBox is inside a DataGridComboBoxColumn?


I have the complete XAML markup below (no code-behind is needed): a Window with a Grid with a DataGrid with a single column of type DataGridComboBoxColumn with its Header and EditingElementStyle properties set in XAML. The EditingElementStyle sets the ItemContainerStyle and the ItemsSource of the ComboBoxes. When I click on a ComboBoxItem, the drop-down does not close and I need it to close.

I tried removing all the contents of the DataGridComboBoxColumn element and the drop-down is there, empty but does not go away when clicking it.

The drop-down also goes away when I click outside the drop-down.

If I put just this in a simple Window:

<ComboBox>
    <ComboBoxItem>a</ComboBoxItem>
    <ComboBoxItem>b</ComboBoxItem>
    <ComboBoxItem>c</ComboBoxItem>
</ComboBox>

it works.

The XAML

<Window x:Class="cs_wpf_test_11.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:cs_wpf_test_11"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="TestWindow" Height="450" Width="800">
    <Grid>
        <DataGrid AutoGenerateColumns="False">
            <DataGrid.ItemsSource>
                <x:Array Type="{x:Type sys:String}">
                    <sys:String>dummy 1</sys:String>
                    <sys:String>dummy 2</sys:String>
                </x:Array>
            </DataGrid.ItemsSource>
            <DataGrid.Columns>
                <DataGridComboBoxColumn Header="My only column">
                    <DataGridComboBoxColumn.EditingElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="ItemContainerStyle">
                                <Setter.Value>
                                    <Style TargetType="ComboBoxItem">
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate>
                                                    <ComboBoxItem Content="{Binding}"/>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </Setter.Value>
                            </Setter>
                            <Setter Property="ItemsSource">
                                <Setter.Value>
                                    <x:Array Type="{x:Type sys:String}">
                                        <sys:String>test 1</sys:String>
                                        <sys:String>test 2</sys:String>
                                        <sys:String>test 3</sys:String>
                                        <sys:String>test 4</sys:String>
                                    </x:Array>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </DataGridComboBoxColumn.EditingElementStyle>
                </DataGridComboBoxColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Expected: the dropdown menu of the ComboBox closes when I click on one of its ComboBoxItems. Actual result: the drop-down remains open.

Update

I wish to use the ItemContainerStyle setter because I change the FontStyle of some ComboBoxItem-s based on a Binding. This is the code from a larger project:

<ComboBoxItem FontStyle="{Binding Path=Style}" Content="{Binding Text}"/>

Based on the accepted answer I use this code for the same effect and the problem is solved:

<Setter Property="ItemContainerStyle">
    <Setter.Value>
        <Style TargetType="ComboBoxItem">
            <Setter Property="FontStyle" Value="{Binding Style}"/>
        </Style>
    </Setter.Value>
</Setter>

Solution

  • The problem is your ItemContainerStyle. Remove that portion and it works as expected.

    Here is what the default ItemContainerStyle consists of. You can use it as a base but if you create a new empty one you are cutting out all this.

    <ControlTemplate TargetType="{x:Type ComboBoxItem}">
        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
            </Trigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="False"/>
                    <Condition Property="IsMouseOver" Value="True"/>
                    <Condition Property="IsKeyboardFocused" Value="False"/>
                </MultiTrigger.Conditions>
                <Setter Property="Background" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewHover.Background}"/>
                <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewHover.Border}"/>
            </MultiTrigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="True"/>
                    <Condition Property="IsMouseOver" Value="False"/>
                    <Condition Property="IsKeyboardFocused" Value="True"/>
                </MultiTrigger.Conditions>
                <Setter Property="Background" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewSelected.Background}"/>
                <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewSelected.Border}"/>
            </MultiTrigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="True"/>
                    <Condition Property="IsMouseOver" Value="True"/>
                </MultiTrigger.Conditions>
                <Setter Property="Background" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewSelectedHover.Background}"/>
                <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewSelectedHover.Border}"/>
            </MultiTrigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="True"/>
                    <Condition Property="IsMouseOver" Value="False"/>
                    <Condition Property="IsKeyboardFocused" Value="False"/>
                </MultiTrigger.Conditions>
                <Setter Property="Background" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewSelectedNoFocus.Background}"/>
                <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewSelectedNoFocus.Border}"/>
            </MultiTrigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="False"/>
                    <Condition Property="IsMouseOver" Value="False"/>
                    <Condition Property="IsKeyboardFocused" Value="True"/>
                </MultiTrigger.Conditions>
                <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewFocus.Border}"/>
            </MultiTrigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="False"/>
                    <Condition Property="IsMouseOver" Value="True"/>
                    <Condition Property="IsKeyboardFocused" Value="True"/>
                </MultiTrigger.Conditions>
                <Setter Property="Background" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewHoverFocus.Background}"/>
                <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource ComboBoxItem.ItemsviewHoverFocus.Border}"/>
            </MultiTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>