Different template for items in ComboBox's drop-down list and for selected item

前端 未结 2 1226
刺人心
刺人心 2020-12-09 11:01

I have a ComboBox with fairly complex template for individual items, which includes two images and several lines of text:

相关标签:
2条回答
  • 2020-12-09 11:40

    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).)

    0 讨论(0)
  • 2020-12-09 11:40

    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>
    
    0 讨论(0)
提交回复
热议问题