Custom WPF ComboBox doesn't show grouping - wpf

I have created a custom ComboBox in WPF
<!-- Combobox template -->
<ControlTemplate x:Key="CustomComboBoxToggleButton" TargetType="ToggleButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Border x:Name="Border" Grid.ColumnSpan="2" CornerRadius="3" Background="{StaticResource CustomDarkBlue}" BorderBrush="{StaticResource CustomWhite}" BorderThickness="2"/>
<Border x:Name="Border2" Grid.Column="0" CornerRadius="3,0,0,3" Margin="1" Background="{StaticResource CustomBackground}" BorderBrush="{StaticResource CustomWhite}" BorderThickness="1,1,2,1"/>
<Path x:Name="Arrow" Grid.Column="1" Fill="{StaticResource CustomGlyph}" 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 CustomDarkBlue}"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource CustomDarkBlue}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource CustomGray}"/>
<Setter TargetName="Border2" Property="BorderBrush" Value="{StaticResource CustomGray}"/>
<Setter Property="Foreground" Value="{StaticResource CustomGray}"/>
<Setter TargetName="Arrow" Property="Fill" Value="{StaticResource CustomGray}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Combobox -->
<Style x:Key="RoundedComboBox" TargetType="{x:Type 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="Foreground" Value="{StaticResource CustomWhite}"/>
<Setter Property="Background" Value="{StaticResource CustomBackground}"/>
<Setter Property="Height" Value="21"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton Name="ToggleButton" Template="{StaticResource CustomComboBoxToggleButton}" 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}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" Margin="3,1,23,1" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<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="{StaticResource CustomBackground}" BorderThickness="2" BorderBrush="{StaticResource CustomWhite}"/>
<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 CustomGray}"/>
</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>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This is then applied to a ComboBox
<ComboBox Grid.Column="0" x:Name="cboChild" Margin="140,65,0,0" ItemsSource="{Binding Source={StaticResource GroupedData}}" ItemTemplate="{StaticResource AccountTemplate}" SelectedValue="{Binding Source={StaticResource Item}, Path=child}" SelectedValuePath="ID" Width="150" Style="{StaticResource RoundedComboBox}" HorizontalAlignment="Left" VerticalAlignment="Top">
<ComboBox.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource GroupHeader}"/>
</ComboBox.GroupStyle>
</ComboBox>
The following is found in Window.Resources
<Window.Resources>
<CollectionViewSource Source="{Binding ChildAccounts}" x:Key="GroupedData">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="group"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<DataTemplate x:Key="GroupHeader">
<TextBlock Text="{Binding group}" Margin="0" Foreground="{StaticResource CustomWhite}"/>
</DataTemplate>
<DataTemplate x:Key="AccountTemplate">
<TextBlock Text="{Binding comment}" Margin="0" Foreground="{StaticResource CustomWhite}"/>
</DataTemplate>
</Window.Resources>
Basically grouping works as it should when the RoundedComboBox style is NOT applied (ie. to the default ComboBox) but whenever the style is applied the drop-down popup is empty
Help!!
Thanks
Andy

Found the answer..... Use <ItemsPresenter ...> instead of <StackPanel ...>
Thanks sa_ddam213 for your helpful advice above regarding the binding.

Related

WPF especific style on selected item according to the style of the item

I have a custom combobox where I apply a specific style on the first item. I want that when this item is selected, the style of displayed text in the combobox is the same. Currently, all selected items appear in the same style and I do not know how to make the ContentPresenter "get" the specified style in that item. This is the code:
<ComboBox HorizontalAlignment="Center" Margin="0,106,0,0" VerticalAlignment="Top" Width="200">
<ComboBoxItem Style="{StaticResource mySpecialStyle}">Select an option...</ComboBoxItem>
<ComboBoxItem>ComboBox Item #1</ComboBoxItem>
<ComboBoxItem>ComboBox Item #2</ComboBoxItem>
<ComboBoxItem>ComboBox Item #3</ComboBoxItem>
</ComboBox>
In fact, "mySpecialStyle" only changes color and fontstyle. But when the first item is selected, it appears like any other selected item. How can set this on the Contentpresenter?
Here is the complete code of the custom ComBoBox:
<Window.Resources>
<Style x:Key="mySpecialStyle" TargetType="{x:Type ComboBoxItem}">
<Setter Property="TextElement.FontStyle" Value="Italic"/>
</Style>
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Border
x:Name="Border"
Grid.ColumnSpan="3"
CornerRadius="3"
Background="#FFFAFAFA"
BorderBrush="#FF999999"
BorderThickness="1" />
<Border
x:Name="Background"
Grid.Column="0"
CornerRadius="3,0,0,3"
Margin="1"
Background="#FFFAFAFA"
BorderBrush="#FF999999"
BorderThickness="0" />
<Path
x:Name="ArrowDw"
Grid.Column="1"
Fill="#FF404040"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"/>
<Path
x:Name="ArrowUp"
Grid.Column="1"
Fill="Transparent"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 2 L 4 -2 L 8 2 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="ArrowDw" Property="Fill" Value="#FF000000" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter TargetName="Background" Property="Background" Value="#FFFFFFFF" />
<Setter TargetName="Border" Property="BorderBrush" Value="#FF000000" />
<Setter TargetName="Border" Property="Background" Value="#FFFFFFFF" />
<Setter TargetName="ArrowDw" Property="Fill" Value="Transparent" />
<Setter TargetName="ArrowUp" Property="Fill" Value="#FF404040" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ToggleButton.IsChecked" Value="True" />
<Condition Property="ToggleButton.IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="ArrowUp" Property="Fill" Value="#FF000000" />
</MultiTrigger.Setters>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="#FFFFFF" />
<Setter TargetName="Border" Property="BorderBrush" Value="#CCCCCC" />
<Setter Property="Foreground" Value="#888888"/>
<Setter TargetName="ArrowDw" Property="Fill" Value="#999999" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
<Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}"/>
</ControlTemplate>
<Style x:Key="{x:Type ComboBox}" TargetType="{x:Type 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="MinHeight" Value="27"/>
<Setter Property="ToolTip" Value="{Binding Path=SelectionBoxItem, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<ToggleButton
Name="ToggleButton"
Template="{StaticResource ComboBoxToggleButton}"
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="8,3,28,3"
VerticalAlignment="Center"
HorizontalAlignment="Left" />
<TextBox x:Name="PART_EditableTextBox"
Style="{x:Null}"
Template="{StaticResource ComboBoxTextBox}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="8,3,28,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="#FFFFFF"
BorderThickness="1"
BorderBrush="#FF999999"/>
<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="27"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#888888"/>
</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.Triggers>
</Style.Triggers>
</Style>
</Window.Resources>
The placeholder "???" is where I need to set the style according to the style defined in the ComboBoxitem (in this case, "mySpecialStyle").
Thanks in advance!
The logic to solve here of course will base on something like a Trigger. However we can't set Style via Setter. So I thought of this hack (but safe enough). Firstly you need to bind the Style of the ContentPresenter to its Tag property (of course 2 way binding by default). Then you just need to change the Tag to a {StaticResource} with ResourceKey being the same as the resource you defined upwards on the tree. This resource should of course have TargetType of ContentPresenter:
<ContentPresenter
Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Style="{Binding Tag, RelativeSource={RelativeSource Self}}" />
<!-- the additional Trigger should be added to the ControlTemplate.Triggers -->
<Trigger Property="SelectedIndex" Value="0">
<Setter TargetName="ContentSite"
Property="Tag" Value="{StaticResource mySpecialStyle}"/>
</Trigger>

WPF template overridden when custom style applied

I have a global style defined for a combobox in app.xaml as below:
<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="MinHeight" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid Width="{TemplateBinding Width}">
<ToggleButton
Name="ToggleButton"
Template="{StaticResource ComboBoxToggleButton}"
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="{StaticResource BackgroundBrush}" />
<ScrollViewer Margin="4,4,4,4" SnapsToDevicePixels="True" Style="{StaticResource DropDownScrollViewer}">
<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 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>
Then I create a combobox in a control:
<ComboBox Name="DataTypeSelector" ItemsSource="{Binding ElementName=DataItemsBuildWindow, Path=DataContext.Types}" SelectedValue="{Binding DataType}" HorizontalAlignment="Stretch" />
The style is applied as expected.
If I change my combobox in the control to the below, the combobox goes back to its original style and the width and triggers defined work. It seems that the new global style is ignored.
<ComboBox Name="DataTypeSelector" ItemsSource="{Binding ElementName=DataItemsBuildWindow, Path=DataContext.Types}" SelectedValue="{Binding DataType}" HorizontalAlignment="Stretch">
<ComboBox.Style>
<Style TargetType="ComboBox">
<Setter Property="Width" Value="160"></Setter>
<Style.Triggers>
<DataTrigger Value="List" Binding="{Binding SelectedValue, ElementName=DataTypeSelector, Converter={StaticResource ToStringConverter}}">
<Setter Property="Width" Value="80" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
How can I keep the global style but also apply the custom triggers?
You have to base the new style on the existing default style:
<ComboBox.Style>
<Style TargetType="ComboBox"
BasedOn="{StaticResource ResourceKey={x:Type ComboBox}}">
...
</Style>
</ComboBox.Style>
By the way, it is not necessary to set the key of the default style in the resource dictionary in App.xaml. If you specify TargetType="ComboBox" the key is set to that type by default. So this is sufficient:
<Style TargetType="ComboBox">
...
</Style>

WPF - "g" is cut off sometimes

I have a combobox in which I display simple strings. At some point this looks like the following:
This is ok. now ein scroll down one step:
Now the "g" is cut off at the bottom. What I have tried so far: Set the height property explicit to Auto. Changing Padding and Margin. Nothing worked. Had some of you the same problem or any suggestions what I could try?
EDIT
Here the related XAML:
<Style x:Key="GraphicEditorInplaceLabelEditStyle">
<Setter Property="ComboBox.Focusable" Value="True"/>
<Setter Property="ComboBox.IsEditable" Value="True"/>
<Setter Property="ComboBox.IsReadOnly" Value="False"/>
<Setter Property="ComboBox.IsTextSearchEnabled" Value="True"/>
<!--Use Separators for empty entries-->
<Setter Property="ComboBox.ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ComboBoxItem}" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="">
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Separator HorizontalAlignment="Stretch"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ComboBox.Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Validation.ValidationAdornerSiteFor="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType=ComboBox}}" Background="{StaticResource ComboBoxActiveBackgroundBrush}" BorderBrush="{StaticResource ComboBoxBorderBrush}" BorderThickness="1" CornerRadius="2">
<Grid>
<ContentPresenter Margin="3,3,3,3" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" HorizontalAlignment="Left" IsHitTestVisible="False" Name="ContentSite" VerticalAlignment="Center" />
<TextBlock Style="{x:Null}" x:Name="PART_TextBackground" Margin="3,3,3,3" Background="Transparent" Focusable="False" FontStyle="Italic" Foreground="LightGray" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<TextBox Style="{x:Null}" x:Name="PART_EditableTextBox" Margin="3,3,3,3" Background="Transparent" Focusable="True" HorizontalAlignment="Left" IsReadOnly="{TemplateBinding IsReadOnly}" VerticalAlignment="Center" Visibility="Hidden">
<TextBox.Template>
<ControlTemplate TargetType="TextBox">
<Border x:Name="PART_ContentHost" Background="{TemplateBinding Background}" Focusable="False" />
</ControlTemplate>
</TextBox.Template>
</TextBox>
<Popup AllowsTransparency="True" Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}" Name="Popup" Placement="Bottom" PopupAnimation="Slide">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" Name="DropDown" SnapsToDevicePixels="True">
<Border x:Name="DropDownBorder" Background="{StaticResource ComboBoxActiveBackgroundBrush}" BorderBrush="{StaticResource ComboBoxBorderBrush}" BorderThickness="1" />
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True" CanContentScroll="False">
<StackPanel KeyboardNavigation.DirectionalNavigation="Contained" IsItemsHost="True" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</Border>
<ToggleButton Grid.Column="1" ClickMode="Press" Focusable="false" IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" Name="ToggleButton" VerticalAlignment="Bottom">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border x:Name="Border"
CornerRadius="2"
Background="{StaticResource ComboBoxActiveBackgroundBrush}"
BorderBrush="{StaticResource ComboBoxBorderBrush}"
BorderThickness="1"
Margin="0,0,0,0" />
<Rectangle x:Name="arrow"
Height="6"
Width="8"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="2"
Fill="{StaticResource ComboBoxArrowDownBrush}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver"
Value="true">
<Setter TargetName="Border"
Property="Background"
Value="{StaticResource ComboBoxMouseOverBackgroundBrush}" />
<Setter TargetName="arrow"
Property="Fill"
Value="{StaticResource ComboBoxArrowDownMouseOverBrush}"></Setter>
</Trigger>
<Trigger Property="ToggleButton.IsChecked"
Value="true">
<Setter TargetName="Border"
Property="Background"
Value="{StaticResource ComboBoxPressedBackgroundBrush}" />
<Setter Property="Fill"
TargetName="arrow"
Value="{StaticResource ComboBoxArrowUpBrush}" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="Border"
Property="Background"
Value="{StaticResource ComboBoxInactiveBackgroundBrush}" />
<Setter Property="Foreground"
Value="{StaticResource FontInactiveBrush}" />
<Setter Property="Fill"
TargetName="arrow"
Value="{StaticResource ComboBoxArrowDownInactiveBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
<ToggleButton.RenderTransform>
<TranslateTransform X="-3" Y="0"></TranslateTransform>
</ToggleButton.RenderTransform>
</ToggleButton>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter Property="Visibility" TargetName="ToggleButton" Value="Collapsed" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource FontInactiveBrush}" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger Property="Popup.AllowsTransparency" SourceName="Popup" Value="true">
<Setter Property="CornerRadius" TargetName="DropDownBorder" Value="4" />
<Setter Property="Margin" TargetName="DropDownBorder" Value="0,2,0,0" />
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Visibility" TargetName="PART_EditableTextBox" Value="Visible" />
<Setter Property="Visibility" TargetName="ContentSite" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I tried to change the padding/margin of the ComboBoxItem as well as the item host stackpanel.

How to group items inside custom control combobox?

I've been trying to group the items of my custom control combobox using xaml and I'm a little stuck. I've been reading around and found the following code that produces the results I want, but I'd like to move all the code into the GroupedImageComboBox control.
<StackPanel>
<StackPanel.Resources>
<CollectionViewSource x:Key="groupedData" Source="{Binding Items}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="EntityBaseDependencyType" Converter="{StaticResource enumConverter}"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</StackPanel.Resources>
<WPFControls:GroupedImageComboBox
ItemsSource ="{Binding Source={StaticResource groupedData}}"
SelectedItem="{Binding SelectedItem}"
>
<ItemsControl.GroupStyle>
<x:Static Member="GroupStyle.Default"/>
</ItemsControl.GroupStyle>
</WPFControls:GroupedImageComboBox>
</StackPanel>
I would like to be able to remove the use of the stackpanel and the itemscontrol from this area and put them inside the GroupedImageComboBox. Is there a way to achieve this?
Thanks in advance.
Edit 1.
I've been playing with the template and feel that I should be able to do the collectionview manipulations within the DropDown grid - I'm just not sure how....
<Style TargetType="{x:Type WPFControls:ImageComboBox}">
<Setter Property="SnapsToDevicePixels" 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="ItemContainerStyle" Value="{StaticResource CustomComboBoxItemStyle}"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="true"/>
<Setter Property="Margin" Value="8"/>
<Setter Property="IsEditable" Value="False"/>
<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">
</ToggleButton>
<ContentPresenter Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{StaticResource DiplayImageWithTextDataTemplate}"
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="{StaticResource WindowBackgroundBrush}"
BorderThickness="1"
BorderBrush="{StaticResource SolidBorderBrush}"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<ItemsPresenter 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="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.Triggers>
</Style.Triggers>
</Style>
Actually, it seems that in this example, the stack panel IS NOT something you HAVE TO use.
Just move the CollectionViewSource declaration elsewhere (in your </Window.Resources><Window.Resources> tag for example) and put your combobox anywhere else you want.

WPF: Refine the look of a grouped ComboBox vs. a grouped DataGrid -sample attached -

just watch this screenshot I made so you see the difference:
I have these requirments to be changed in the ComboBox`s PopUp so it looks like the grouped WPF DataGrid, its only about the Popup-area, do not judge the editable area of the ComboBox or that there is no Header... Important are these things, because I could not change them:
ComboBox:
(Green Line) The alternating
Background of the Item must start at
the beginning
(Red Line) The TextBlocks within the
Border must be aligned Center OR
Right1.
(Blue) The weakly visible horizontal
Border must always stretch to the
right side or take all space2.
to 1.) I have no idea why there is a margin
to 2.) HorizontalAlignment of the TextBlock does not work
to 3.) I can make the stackpanel in the ItemTemplate of the Combobox a read background then you can see very well the red color has a margin somehow on the right and left side. Have no idea how to remove that.
Anyone can help, please?
If you want to see the textbox live just download it here:
http://www.sendspace.com/file/6lmbrh
Its a 30 kb VS2010 .NET 4.0 project.
Here is the XAML for the ComboBox:
<Window x:Class="TestComboGrouped.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="200">
<Window.Resources>
<Style x:Key="ComboBoxItemStyle" TargetType="ComboBoxItem">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="ComboBox.AlternationIndex" Value="0">
<Setter Property="Background" Value="White"></Setter>
</Trigger>
<Trigger Property="ComboBox.AlternationIndex" Value="1">
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush RenderOptions.EdgeMode="Aliased" StartPoint="0.5,0.0" EndPoint="0.5,1.0">
<GradientStop Color="#FFFEFEFF" Offset="0"/>
<GradientStop Color="#FFE4F0FC" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="ComboBoxBorderStyle" TargetType="Border">
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="BorderBrush" Value="#FFCEDFF6" />
<Setter Property="BorderThickness" Value="1 0 0 1" />
</Style>
<Style x:Key="ComboBoxStyle" BasedOn="{StaticResource {x:Type ComboBox}}" TargetType="{x:Type ComboBox}">
<Setter Property="ItemContainerStyle" Value="{StaticResource ComboBoxItemStyle}"/>
</Style>
<!-- Grouped CollectionView -->
<CollectionViewSource Source="{Binding WeeklyDateList,IsAsync=False}" x:Key="WeeklyView">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="MonthName"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<StackPanel>
<ComboBox
ItemsSource="{Binding Source={StaticResource ResourceKey=WeeklyView}}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Style="{StaticResource ComboBoxStyle}"
AlternationCount="2"
MaxDropDownHeight="300"
Width="Auto"
x:Name="comboBox"
>
<ComboBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock
Padding="5,0,0,0"
Background="White"
Foreground="DarkBlue"
FontSize="14"
FontWeight="DemiBold"
Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ComboBox.GroupStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border Style="{StaticResource ComboBoxBorderStyle}">
<TextBlock Width="100" Foreground="Purple" Text="{Binding WeeklyLessonDate, StringFormat='yyyy-MM-dd'}"/>
</Border>
<Border Style="{StaticResource ComboBoxBorderStyle}">
<TextBlock Padding="5,0,5,0" Width="40" Text="{Binding WeekNumber}"/>
</Border>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Window>1.2.
UPDATE:
#Meleak thats the updated image it looks very nice thanks to you:
I was just about to put my old 2-"ColumnHeader" in that ComboBox`s Popup top area but I could not find anymore my sample... seems due to changing/trying a lot I have overritten that code :/ I know I did it in the controltemplate above the scrollviewer with a stackpanel or a grid with 2 rowdefinitions. But your code looks now totally different to my default combobox controltemplate I have no idea how to merge both code snippets.
I think that was the code where I put the 2 "column headers", just search for inside the POPUP
<Style x:Key="ComboBoxStyle1" TargetType="{x:Type ComboBox}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Padding" Value="4,3"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid x:Name="MainGrid" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
<Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
<Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
// Here should be the column headers, but how merge your code with the ItemsPresenter?
<ScrollViewer x:Name="DropDownScrollViewer">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ScrollViewer>
</Border>
</Microsoft_Windows_Themes:SystemDropShadowChrome>
</Popup>
<ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxReadonlyToggleButton}"/>
<ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
<Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
<Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
<Setter Property="Background" Value="#FFF4F4F4"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
<Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
<Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEditable" Value="true">
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/>
</Trigger>
</Style.Triggers>
</Style>
I think it looks pretty close. You can download my modified version from here
Added a template for ComboBoxItem
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<Style x:Key="ComboBoxItemStyle" TargetType="ComboBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Grid HorizontalAlignment="Stretch"
Margin="-5,0,0,0"
Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="45"/>
</Grid.ColumnDefinitions>
<Border Name="border1"
BorderThickness="0,0,1,1"
BorderBrush="#FFCEDFF6"
Grid.Column="0">
<TextBlock Foreground="Purple"
HorizontalAlignment="Right"
Margin="0,0,2,0"
Text="{Binding WeeklyLessonDate, StringFormat='yyyy-MM-dd'}"/>
</Border>
<Border Name="border2"
BorderThickness="0,0,1,1"
BorderBrush="#FFCEDFF6"
Grid.Column="1">
<TextBlock HorizontalAlignment="Center"
Text="{Binding WeekNumber}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="border1" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/>
<Setter TargetName="border2" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="ComboBox.AlternationIndex" Value="0">
<Setter Property="Background" Value="White"></Setter>
</Trigger>
<Trigger Property="ComboBox.AlternationIndex" Value="1">
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush RenderOptions.EdgeMode="Aliased" StartPoint="0.5,0.0" EndPoint="0.5,1.0">
<GradientStop Color="#FFFEFEFF" Offset="0"/>
<GradientStop Color="#FFE4F0FC" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>

Resources