【问题标题】:Different template for items in ComboBox's drop-down list and for selected item组合框下拉列表中的项目和选定项目的不同模板
【发布时间】:2011-11-26 14:30:01
【问题描述】:

我有一个ComboBox,其中包含相当复杂的单个项目模板,其中包括两个图像和几行文本:

但是,ComboBox 中的选中项本身并不能正确显示,因为垂直空间太有限(我不能让它更高,因为它是ToolBar 的一部分)。

如何让 ComboBox 为 ComboBox 本身中显示的项目使用不同的模板?(默认的 ToString 表示就可以了)

谢谢!

【问题讨论】:

  • 是使用 DataTemplateSelector 为您解决问题还是您正在寻找其他解决方案?也许我没有得到正确的问题?
  • @sll 我不认为 DataTemplateSelector 可以做到这一点(虽然我没有尝试过),IIRC 只有在加载项目时才会评估它。无论如何,我更喜欢一些更简单的解决方案,它不涉及我创建的每个 ComboBox 的类(会有几个)。
  • 好的,你想达到什么目的?基于某些标准的项目的不同 UI 表示?
  • @sll 如图所示,ComboBox 中当前选中的项目没有正确显示。我只是想解决这个问题。
  • 图像是如何绘制的?它们是从文件加载还是使用 WPF 工具以某种方式绘制?

标签: wpf xaml datatemplate


【解决方案1】:

所选项目(在 ComboBox 本身中,而不是下拉菜单中)不在 ComboBoxItem 内,因此您可以执行以下操作:

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

(编辑:请注意,选择框中的绑定会抛出错误,因为找不到RelativeSource。有多种选项可以规避这一点,一个是自定义值转换器,根据祖先是否存在返回truefalse(手动树行走)。)

【讨论】:

  • 我想知道 WPF 团队在设计 ComboBox 时的想法。克服这个问题的 naive 方法是什么(当在 2 个地方使用数据模板时:用于项目列表和隐藏列表时用于选定项目)?带有样式的ContentControl 似乎是处理多个模板的常见hack(而不是DataTemplateSelector 的糟糕想法),但我真的很讨厌检查祖先,这反过来也有根据最新编辑的问题。
【解决方案2】:

我正在寻找一个标准(不是 hacky 并且没有绑定错误)解决方案来解决这个问题。我发现它here:使用DataTemplateSelector

这与 @H.B. answer 的想法相同:检查视觉树中是否有 ComboBoxItem 作为父级。

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;
    }
}

用法:

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

【讨论】:

  • 选择后效果很好。但在 Init 上未调用 SelectTemplate 函数。
  • @LWS,什么是“初始化”?为什么要在 init 时调用它而不是在组合框决定时调用它?可能值得提出一个问题,如果没有minimal reproducible example,我怀疑能否提供帮助。
  • 加载对话框时。我的组合框是空的。第一次选择后一切正常。我只是使用你的代码,没有任何修改。
猜你喜欢
  • 2012-08-23
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多