This is my combo-box.
There is a pretty good answer to your question here if you don't want to change the ComboBoxes style: https://stackoverflow.com/a/2277488/1070906
It uses a Trigger in the DataTemplate which looks if there is a ComboBoxItem somewhere above in the visual tree, which is not the case in the selection box.
You could override the ComboBox and change the SelectionBoxItemTemplate directly.
public class SelectionComboBox : ComboBox
{
#region Properties
#region Dependency Properties
public DataTemplate AltSelectionBoxItemTemplate
{
get { return (DataTemplate)GetValue(AltSelectionBoxItemTemplateProperty); }
set { SetValue(AltSelectionBoxItemTemplateProperty, value); }
}
public static readonly DependencyProperty AltSelectionBoxItemTemplateProperty =
DependencyProperty.Register("AltSelectionBoxItemTemplate", typeof(DataTemplate), typeof(SelectionComboBox), new UIPropertyMetadata(null, (s, e) =>
{
// For new changes...
if ((s is SelectionComboBox) && ((SelectionComboBox)s).Presenter != null && (e.NewValue is DataTemplate))
((SelectionComboBox)s).Presenter.ContentTemplate = (DataTemplate)e.NewValue;
// Set the new value
((SelectionComboBox)s).AltSelectionBoxItemTemplate = (DataTemplate)e.NewValue;
}));
#endregion
#region Internals
#region Elements
ContentPresenter Presenter { get; set; }
#endregion
#endregion
#endregion
#region Constructors
#endregion
#region Methods
#region Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Presenter = this.GetTemplateChild("contentPresenter") as ContentPresenter;
// Directly Set the selected item template
if (AltSelectionBoxItemTemplate != null) Presenter.ContentTemplate = AltSelectionBoxItemTemplate;
}
#endregion
#endregion
}
Once you define the control, you could style it.
<controls:SelectionComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}">
<controls:SelectionComboBox.AltSelectionBoxItemTemplate>
<DataTemplate>
<!-- My Template Goes Here... -->
</DataTemplate>
</controls:SelectionComboBox.AltSelectionBoxItemTemplate>
</controls:SelectionComboBox>
Instead of using the read-only SelectionBoxItemTemplate property I created a new (attached, writable) property and used that one in my style. I also added a trigger to my style to not break all the comboboxes that are not using my new attached property...
Use it like this:
<ComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}">
<controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate>
<DataTemplate DataType="{x:Type ...}">
... Template for the selection box ...
</DataTemplate>
</controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate>
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type ...}">
... Template for the popup ...
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You just have to add this class to your project:
public class ComboBoxSelectionBoxAltTemplateBehaviour
{
public static readonly DependencyProperty SelectionBoxAltTemplateProperty = DependencyProperty.RegisterAttached(
"SelectionBoxAltTemplate", typeof (DataTemplate), typeof (ComboBoxSelectionBoxAltTemplateBehaviour), new PropertyMetadata(default(DataTemplate)));
public static void SetSelectionBoxAltTemplate(DependencyObject element, DataTemplate value)
{
element.SetValue(SelectionBoxAltTemplateProperty, value);
}
public static DataTemplate GetSelectionBoxAltTemplate(DependencyObject element)
{
return (DataTemplate) element.GetValue(SelectionBoxAltTemplateProperty);
}
}
and change your ComboBox style to use the SelectionBoxAltTemplate attached property if set (or because I could not set a trigger to "not null", I set it back to the default SelectionBoxItemTemplate if the attached one is null):
The ContentPresenter inside the ControlTemplate of the ComboBox Style:
<ContentPresenter Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" />
And the Trigger to provide backwards compatibility to ComboBoxed without the attached Property:
<ControlTemplate.Triggers>
<Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" />
</Trigger>
...
</ControlTemplate.Triggers>
Full Style:
<Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value="{StaticResource ComboBoxBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ComboBoxBorder}"/>
<Setter Property="Margin" Value="6"/>
<Setter Property="Padding" Value="3,3,5,3"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Name="Border" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
<ToggleButton Name="ToggleButton2" Focusable="False" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Grid.ColumnSpan="2" Background="Transparent"/>
<!-- Allows clicking anywhere on the combobox, not only the visible button on the right -->
<ToggleButton Focusable="false" Grid.Column="1" x:Name="ToggleButton" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Style="{StaticResource ComboBoxToggleButton}"/>
<ContentPresenter HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False" />
<TextBox Visibility="Hidden" HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" Background="Transparent" />
<Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
<Border x:Name="DropDownBorder" Background="{StaticResource ComboBoxBackground}" BorderBrush="{StaticResource ComboBoxBorder}" BorderThickness="1" Padding="0,4">
<ScrollViewer SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Style="{x:Null}" >
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Border>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" />
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="MinHeight" Value="95" TargetName="DropDownBorder" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox" />
<Setter Property="Visibility" Value="Hidden" TargetName="ContentSite" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true" SourceName="ToggleButton2">
<Setter Property="Background" Value="{StaticResource ComboBoxMouseOver}" />
</Trigger>
<Trigger Property="HasItems" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However this might not work with ItemTemplateSelctors, only with one single template - but you could easily add an attached property "SelectionBoxAltTemplateSelector" which provides the selector and passes that one to the style.
If the ComboBox's IsEditable property is set to True, you can set the "TextSearch.TextPath" property of the ComboBox to the property name you want to show. So in your case:
<ComboBox IsEditable="True" TextSearch.TextPath="FullName" .../>
Unfortunately, the SelectionBoxItemTemplate
is a readonly property, so we have to do a bit more work. By doing the ItemTemplate
to be how you want the item to appear when selected, you can edit the ItemContainerStyle
to provide a ControlTemplate
that includes the other fields you want to display.
<ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216">
<ComboBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding FullName}" Width="150" />
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<StackPanel Orientation="Horizontal">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<Label Content="{Binding Title}" Width="100"/>
<Label Content="{Binding BranchName}" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
For the ComboBoxItem
template, I just modified the default one, so it should be fully functional.