JohanDNB JohanDNB - 10 days ago 4
C# Question

Show selected item in ComboBox with custom item template

I used the code from this page to style my combobox: How to style ComboBox Background on Mouse Hover?

I've changed my default item template, but now they won't appear in the selected value area. In the image below you can see the problem and what I want to achieve.

Screenshot showing desired effect

This is my XAML in App.xaml:

<LinearGradientBrush x:Key="ButtonBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFF3F3F3"/>
<GradientStop Offset="0.3" Color="#FFCCCCCC"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFF3F3F3"/>
<GradientStop Offset="0.3" Color="#FFCCCCCC"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundHoverBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFE4E4E4"/>
<GradientStop Offset="0.3" Color="#FFBBBBBB"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundDisabledBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FF636363"/>
<GradientStop Offset="0.3" Color="#FF4E4D4D"/>
</LinearGradientBrush>

<SolidColorBrush x:Key="GlyphBrush" Color="#FFF" />

<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />

<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />

<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>

<Border x:Name="Border" Grid.ColumnSpan="2" CornerRadius="2" Background="{StaticResource ButtonBackgroundBrush}" BorderBrush="#FF898989" BorderThickness="1" />
<Border x:Name="Border2" Grid.Column="0" CornerRadius="2,0,0,2" Margin="1" Background="White" BorderBrush="#FF898989" BorderThickness="0,0,1,0" />

<Path x:Name="Arrow" Grid.Column="1" Fill="{StaticResource GlyphBrush}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ButtonBackgroundHoverBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="#FF59B7FF" />
<Setter TargetName="Border2" Property="BorderBrush" Value="#FF59B7FF" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ButtonBackgroundHoverBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="#FF59B7FF" />
<Setter TargetName="Border2" Property="BorderBrush" Value="#FF59B7FF" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource ButtonBackgroundDisabledBrush}" />
<Setter TargetName="Arrow" Property="Fill" Value="{StaticResource DisabledForegroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

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

<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}" Grid.Column="2" Focusable="False" IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" />
<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="White" BorderThickness="1" BorderBrush="#FF898989" />
<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="{StaticResource DisabledForegroundBrush}"/>
</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,0,2,2"/>
<Setter TargetName="DropDownBorder" Property="Margin" Value="0,-1,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:Name="CustomComboboxItem" TargetType="ComboBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
<RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding NewItemName}" Grid.Row="0" FontWeight="Bold" />
<TextBlock Text="{Binding NewItemComment}" Grid.Row="1" FontStyle="Italic" Foreground="#FF555454" />
</Grid>
</Grid>

<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


MainWindow.xaml:

<ComboBox Height="40" HorizontalAlignment="Left" Margin="102,64,0,0" Name="comboBox1" VerticalAlignment="Top" Width="459" />


Code-behind:

public MainWindow()
{
InitializeComponent();

comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 1", NewItemComment = "hello :)" });
comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 2", NewItemComment = "hello :)" });
comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 3", NewItemComment = "hello :)" });
comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 4", NewItemComment = "hello :)" });
comboBox1.Items.Add(new CustomComboboxItem { NewItemName = "Item 5", NewItemComment = "hello :)" });
}

public class CustomComboboxItem
{
public string NewItemName { get; set; }
public string NewItemComment { get; set; }
}


Can someone tell me what I'm doing wrong?

Answer

You can define ItemTemplate for ComboBox instead of ControlTemplate for ComboBoxItem to achieve that. As you can see, ControlTemplate for ComboBoxItem doesn't affect selected item appearance when ItemTemplate does. Following is content of your CustomComboboxItem Style merged within ComboBox Style :

<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">
        ........
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <Grid.Style>
                            <Style TargetType="Grid">
                                <Style.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="Background" Value="LightGray"/>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Grid.Style>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid Grid.Column="1">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
                                <RowDefinition Height="16" MinHeight="16" MaxHeight="16" />
                            </Grid.RowDefinitions>
                            <TextBlock Text="{Binding NewItemName}" Grid.Row="0" FontWeight="Bold" />
                            <TextBlock Text="{Binding NewItemComment}" Grid.Row="1" FontStyle="Italic" Foreground="#FF555454" />
                        </Grid>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        ........
    </Style>