我想在ComboBox中显示自定义模板/项目作为选定项目(此项目实际上不存在于项目列表中,并且更新方式不同)。这甚至不需要是一个项目,只需提供自定义视图即可。
如何在保持当前ComboBox主题的同时执行此操作(因此无法替换ControlTemplate)?据我所知,所有SelectionBox *属性都不可编辑,内部ComboBox使用未命名的ContentPresenter。
答案 0 :(得分:20)
我会这样做:
<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
内,具体取决于您的偏好。
答案 1 :(得分:0)
如果我直截了当,你想要一个随意显示的控件以及一个下拉按钮,它会显示一个带有复选框的项目列表吗?
我甚至不愿意尝试重新设置ComboBox
来实现这一目标。问题是ComboBox
在不同于您需要的路径上更专业。如果您查看ComboBox ControlTemplate Example,您会看到它只是使用Popup
控件来显示可能的值列表。
您可以将该模板的各个部分作为创建UserControl
的指导,以便更容易理解并更好地提供您想要的内容。您甚至可以添加SelectedItems
属性,ComboBox
无法提供。
我的意思是指导的一个例子:Popup
有一个IsOpen
属性。在控件模板中,它设置为{TemplateBinding IsDropDownOpen}
,这意味着ComboBox
类具有IsDropDownOpen
属性,该属性已更改以控制Popup
的展开/折叠
答案 2 :(得分:0)
Alexey Mitev对Ray Burns'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>
答案 3 :(得分:-1)