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

2019-05-12 05:38发布

我想显示自定义模板/项目在ComboBox中选定的项目(这个项目实际上并不存在的项目列表中,并以不同更新)。 这不,甚至需要有一个项目,只是提供了一个自定义视图会工作。

我怎样才能做到这一点,而目前的组合框主题(所以没有控件模板更换可能)内停留? 据我所见,所有SelectionBox的*属性是不可编辑和国内的ComboBox使用无名ContentPresenter。

Answer 1:

我会做这样的:

<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 ,根据自己的喜好。



Answer 2:

如果我有这个直,你想有一个下拉按钮显示的项目与旁边的复选框列表一起显示的东西任意控制?

我甚至不会费劲去尝试再整一个ComboBox来实现这一目标。 问题是, ComboBox更专业下来比你需要一个不同的路径。 如果你看一下组合框控件模板实例 ,你会看到,它只是采用了Popup控件来显示可能值的列表。

你可以把该模板为指导的作品创造一个UserControl是容易理解和更好地提供你想要的。 你甚至就可以添加SelectedItems属性并且使得ComboBox不提供。

什么我通过指导的意思是一个例子:在PopupIsOpen属性。 在控制模板,它被设置为{TemplateBinding IsDropDownOpen}这意味着该ComboBox类有一个IsDropDownOpen是为了控制的展开/折叠改变属性Popup



Answer 3:

阿列克谢Mitev对雷伯恩斯评论回答启发我写以下合理的短实用工具类,我现在在我所有的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>


Answer 4:

你需要寻找到触发器和样式 。 您可能还需要寻找到一些我在这里StackOverflow上旧的问题,帮助我克服了这些问题:

  • 仅显示在ListViewItem的内容被选中
  • Windows Presentation Foundation中使用样式


文章来源: WPF: How to customize SelectionBoxItem in ComboBox