Другой вариант - использовать ItemTemplateSelector
вместо ItemTemplate
. Я использовал это следующим образом.
ComboBoxItemTemplateSelector
происходит от DataTemplateSelector
и имеет два прикрепленных свойства, SelectedTemplate
и DropDownTemplate
. Затем мы устанавливаем DataTemplates из Xaml следующим образом
<ComboBox ItemsSource="{Binding Persons}"
ItemTemplateSelector="{StaticResource ComboBoxItemTemplateSelector}">
<ts:ComboBoxItemTemplateSelector.SelectedTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</ts:ComboBoxItemTemplateSelector.SelectedTemplate>
<ts:ComboBoxItemTemplateSelector.DropDownTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding LastName}" />
</StackPanel>
</DataTemplate>
</ts:ComboBoxItemTemplateSelector.DropDownTemplate>
</ComboBox>
В SelectTemplate мы проверяем, обернут ли текущий контейнер в ComboBoxItem
и, если это так, мы возвращаем DropDownTemplate
. В противном случае мы возвращаем SelectedTemplate
.
public class ComboBoxItemTemplateChooser : DataTemplateSelector
{
#region SelectedTemplate..
#region DropDownTemplate..
public override DataTemplate SelectTemplate(object item,
DependencyObject container)
{
ComboBox parentComboBox = null;
ComboBoxItem comboBoxItem = container.GetVisualParent<ComboBoxItem>();
if (comboBoxItem == null)
{
parentComboBox = container.GetVisualParent<ComboBox>();
return ComboBoxItemTemplateChooser.GetSelectedTemplate(parentComboBox);
}
parentComboBox = ComboBox.ItemsControlFromItemContainer(comboBoxItem) as ComboBox;
return ComboBoxItemTemplateChooser.GetDropDownTemplate(parentComboBox);
}
}
Небольшой демонстрационный проект, который использует это, можно скачать здесь: ComboBoxItemTemplateDemo.zip
Я также сделал небольшой пост в блоге об этом здесь: Другой шаблон элемента ComboBox для выпадающего списка . Также показан другой очевидный способ сделать то же самое, но со свойствами вместо прикрепленных свойств в ComboBoxItemTemplateSelector
.
Да, и GetVisualParent. У каждого, кажется, есть свои собственные реализации этого, но в любом случае вот тот, который я использую
public static class DependencyObjectExtensions
{
public static T GetVisualParent<T>(this DependencyObject child) where T : Visual
{
while ((child != null) && !(child is T))
{
child = VisualTreeHelper.GetParent(child);
}
return child as T;
}
}