代码之家  ›  专栏  ›  技术社区  ›  Andrey Shchekin

WPF:如何在组合框中自定义SelectionBoxItem

  •  7
  • Andrey Shchekin  · 技术社区  · 15 年前

    我希望在组合框中将自定义模板/项显示为选中项(此项实际上不存在于项列表中,更新方式不同)。这甚至不需要是一个项目,只要提供一个自定义视图就可以了。

    如何在保持当前组合框主题(因此无法替换ControlTemplate)的同时执行此操作?据我所见,所有SelectionBox*属性都不可编辑,并且内部组合框使用未命名的ContentPresenter。

    4 回复  |  直到 7 年前
        1
  •  19
  •   dotNET    10 年前

    我会这样做:

    <Window.Resources>
    
      <DataTemplate x:Key="NormalItemTemplate" ...>
        ...
      </DataTemplate>
    
      <DataTemplate x:Key="SelectionBoxTemplate" ...>
        ...
      </DataTemplate>
    
      <DataTemplate x:Key="CombinedTemplate">
        <ContentPresenter x:Name="Presenter"
           Content="{Binding}"
           ContentTemplate="{StaticResource NormalItemTemplate}" />
        <DataTemplate.Triggers>
          <DataTrigger
            Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
            Value="{x:Null}">
            <Setter TargetName="Presenter" Property="ContentTemplate"
                    Value="{StaticResource SelectionBoxTemplate}" />
          </DataTrigger>
        </DataTemplate.Triggers>
      </DataTemplate>
    
    </Window.Resources>
    
    ...
    
    <ComboBox
      ItemTemplate="{StaticResource CombinedTemplate}"
      ItemsSource="..."
      ... />
    

    这样做的原因是 CombinedTemplate 通常只使用NormalItemTemplate显示其数据,但如果没有 ComboBoxItem 它假定它在选择框中,因此使用SelectionBoxTemplate。

    注意这三个 DataTemplates 可以包括在任何级别的 ResourceDictionary (不仅仅是在 Window 水平)甚至直接在 ComboBox ,取决于您的喜好。

        2
  •  0
  •   Joel B Fant    15 年前

    如果我是直截了当的,你想要一个任意显示的控件,以及一个下拉按钮,显示一个旁边有复选框的项目列表?

    我甚至不想费心重新设计 ComboBox 为了达到这个目的。问题是 组合框 比你需要的更专业化。如果你看 ComboBox ControlTemplate Example ,您将看到它只使用 Popup 控件以显示可能值的列表。

    您可以将该模板的各个部分作为创建 UserControl 这更容易理解,更好地提供您想要的。您甚至可以添加 SelectedItems 财产,以及 组合框 不提供。

    我所说的指导的一个例子: 弹出窗口 有一个 IsOpen 属性。在控件模板中,它设置为 {TemplateBinding IsDropDownOpen} 也就是说 组合框 类有一个 IsDropDownOpen 为控制 弹出窗口 .

        3
  •  0
  •   dlf    7 年前

    亚历克赛·米特夫对雷·伯恩斯的评论 answer 启发我编写以下相当短的实用程序类,我现在在所有WPF项目中都使用它:

    public class ComboBoxItemTemplateSelector : DataTemplateSelector
    {
        public List<DataTemplate> SelectedItemTemplates { get; } = new List<DataTemplate>();
        public List<DataTemplate> DropDownItemTemplates { get; } = new List<DataTemplate>();
    
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            return GetVisualParent<ComboBoxItem>(container) == null
                ? ChooseFrom(SelectedItemTemplates, item)
                : ChooseFrom(DropDownItemTemplates, item);
        }
    
        private static DataTemplate ChooseFrom(IEnumerable<DataTemplate> templates, object item)
        {
            if (item == null)
                return null;
            var targetType = item.GetType();
            return templates.FirstOrDefault(t => (t.DataType as Type) == targetType);
        }
    
        private static T GetVisualParent<T>(DependencyObject child) where T : Visual
        {
            while (child != null && !(child is T))
                child = VisualTreeHelper.GetParent(child);
            return child as T;
        }
    }
    

    在工具箱中,可以这样编写XAML:

    <UserControl.Resources>
         <DataTemplate x:Key="SelectedItemTemplateForInt" DataType="{x:Type system:Int32}">
             <!-- ... -->
         </DataTemplate>
    
         <DataTemplate x:Key="SelectedItemTemplateForDouble" DataType="{x:Type system:Double}">
             <!-- ... -->
         </DataTemplate>
    
         <DataTemplate x:Key="DropDownItemTemplateForInt" DataType="{x:Type system:Int32}">
             <!-- ... -->
         </DataTemplate>
    
         <DataTemplate x:Key="DropDownItemTemplateForDouble" DataType="{x:Type system:Double}">
             <!-- ... -->
         </DataTemplate>
    </UserControl.Resources>
    
    <ComboBox>
        <ComboBox.ItemTemplateSelector>
            <local:ComboBoxItemTemplateSelector>
                <local:ComboBoxItemTemplateSelector.SelectedItemTemplates>
                    <StaticResource ResourceKey="SelectedItemTemplateForInt" />
                    <StaticResource ResourceKey="SelectedItemTemplateForDouble" />
                </local:ComboBoxItemTemplateSelector.SelectedItemTemplates>
    
                <local:ComboBoxItemTemplateSelector.DropDownItemTemplates>
                    <StaticResource ResourceKey="DropDownItemTemplateForInt" />
                    <StaticResource ResourceKey="DropDownItemTemplateForDouble" />
                </local:ComboBoxItemTemplateSelector.DropDownItemTemplates>
            </local:ComboBoxItemTemplateSelector>
        </ComboBox.ItemTemplateSelector>
    </ComboBox>
    
        4
  •  -1
  •   Community CDub    7 年前

    你需要调查一下 Triggers Styles . 您可能还想看看我在StackOverflow上的一些老问题,这些问题帮助我克服了这些问题: