I have a ComboBox
with fairly complex template for individual items, which includes two images and several lines of text:
However, the selected item in the ComboBox
itself doesn't display correctly, because the vertical space is too limited (I can't make it higher, because it is a part of a ToolBar
).
How can I make the ComboBox use a different template for the item which is displayed in the ComboBox
itself? (the default ToString
representation would do just fine)
Thanks!
The selected item (in the ComboBox
itself, not the dropdown) is not inside a ComboBoxItem
so you can do something like this:
<ComboBox.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<!-- Complex default template -->
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{Binding XPath=media:thumbnail/@url}" Width="100" Height="100" />
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<!-- Simple selection box template -->
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource AncestorType=ComboBoxItem}}"
Value="{x:Null}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding XPath=title}" />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</ComboBox.ItemTemplate>
(Edit: Note that the binding in the for the selection box will throw errors because the RelativeSource
is not found. There are various options of circumventing this, one being a custom value converter that returns true
or false
depending on whether the ancestor exists (manual tree walking).)
I was searching for a standard (not hacky and without binding errors) solution to this problem. And I found it here: using DataTemplateSelector
.
It's the same idea as per @H.B. answer: check whenever there is a ComboBoxItem
as a parent in visual tree.
public class ComboBoxItemTemplateSelector : DataTemplateSelector
{
public DataTemplate SelectedTemplate { get; set; }
public DataTemplate DropDownTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
while (container != null)
{
container = VisualTreeHelper.GetParent(container);
if (container is ComboBoxItem)
return DropDownTemplate;
}
return SelectedTemplate;
}
}
Usage:
<ComboBox.ItemTemplateSelector>
<local:ComboBoxItemTemplateSelector>
<local:ComboBoxItemTemplateSelector.SelectedTemplate>
<DataTemplate>
... simple template for selected item
</DataTemplate>
</local:ComboBoxItemTemplateSelector.SelectedTemplate>
<local:ComboBoxItemTemplateSelector.DropDownTemplate>
<DataTemplate>
... complex template used by dropdown items
</DataTemplate>
</local:ComboBoxItemTemplateSelector.DropDownTemplate>
</local:ComboBoxItemTemplateSelector>
</ComboBox.ItemTemplateSelector>