我想在Silverlight中显示ComboBox
以及OPTGROUP
样式的标题横幅。我发现每个网站(包括关于SO的问题)都可以将此链接粘贴到一个过时的链接上,并且很方便地不显示任何代码片段供我使用。显示Silverlight的组合框标题
例如为:
那么,如何做到这一点?
我想在Silverlight中显示ComboBox
以及OPTGROUP
样式的标题横幅。我发现每个网站(包括关于SO的问题)都可以将此链接粘贴到一个过时的链接上,并且很方便地不显示任何代码片段供我使用。显示Silverlight的组合框标题
例如为:
那么,如何做到这一点?
见我类似的问题:How to show group header for items in Silverlight combobox? 我把虚拟条目中收集源指示组头,然后修改DataTemplate中显示的组头以不同的方式和以不同的方式正常输入。
以下是一种通用方法。这并不坏,应该足够灵活 - 尽管它有需要扩展集合类的弱点(不能使用CollectionViewSource)。
步骤1ComboBoxGroupHeader对象
此播放由@NiteshChordiya提到的 “虚拟条目” 的作用。
public class ComboBoxGroupHeader
{
public ComboBoxGroupHeader(object header)
{
Header = header;
}
public object Header { get; protected set; }
}
步骤2扩展组合框
这将覆盖PrepareContainerForItemOverride
,为了与虚拟项的容器进行修补。它还提供了一个(可选)“HeaderTemplate”。
public class GroupedComboBox : ComboBox
{
public DataTemplate HeaderTemplate
{
get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
set { SetValue(HeaderTemplateProperty, value); }
}
public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(GroupedComboBox), new PropertyMetadata(null));
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var container = element as ComboBoxItem;
if (container != null && item is ComboBoxGroupHeader)
{
// prevent selection
container.IsHitTestVisible = false;
// adjust the container to display the header content
container.ContentTemplate = HeaderTemplate
container.Content = ((ComboBoxGroupHeader)item).Header;
}
}
}
步骤3扩展集合类
这确实分组,并添加虚拟 “ComboBoxGroupHeader” 条目。此实现基本上只读(分组会,如果你想添加新项目打破),但它是直截了当的,以支持像“添加”操作,“插入”等
public class GroupedCollection<T, TGroup> : ObservableCollection<object>
{
private Func<T, TGroup> _grouping;
public IEnumerable<T> BaseItems
{
get { return base.Items.OfType<T>(); }
}
public GroupedCollection(IEnumerable<T> initial, Func<T, TGroup> grouping)
: base(GetGroupedItems(initial, grouping))
{
_grouping = grouping;
}
private static IEnumerable<object> GetGroupedItems(IEnumerable<T> items, Func<T, TGroup> grouping)
{
return items
.GroupBy(grouping)
.SelectMany(grp =>
new object[] { new ComboBoxGroupHeader(grp.Key) }
.Union(grp.OfType<object>())
);
}
}
用法
它像一个正常ComboBox
,与可选的HeaderTemplate
:
<local:GroupedComboBox ItemsSource="{Binding Source}">
<local:GroupedComboBox.HeaderTemplate>
<TextBlock FontSize="9" TextDecorations="Underline" Foreground="DarkGray"
Text="{Binding}" />
</local:GroupedComboBox.HeaderTemplate>
</local:GroupedComboBox>
对于分组以生效,源必须使用“GroupedCollection”上方,以便includ e虚拟标题项目。例如:
public class Item
{
public string Name { get; set; }
public string Category { get; set; }
public Item(string name, string category)
{
Name = name;
Category = category;
}
}
public class Items : GroupedCollection<Item, string>
{
public Items(IEnumerable<Item> items)
: base(items, item => item.Category) { }
}
public class ViewModel
{
public IEnumerable<Item> Source { get; private set; }
public ViewModel()
{
Source = new Items(new Item[] {
new Item("Apples", "Fruits"),
new Item("Carrots", "Vegetables"),
new Item("Bananas", "Fruits"),
new Item("Lettuce", "Vegetables"),
new Item("Oranges", "Fruits")
});
}
}
请注意:尽管控件将“IsHitTestVisible”设置为false,但仍可通过键盘选择标题项目。您需要重写'OnKeyDown'并检查箭头键和向上翻页 - 要么禁用它们,要么实现自定义索引更新逻辑。 – Impworks
这些项目是静态的还是像集合绑定的? –
他们将是一个绑定集合 – Chris
我可以发誓我过去通过将HeaderedItemsControl放置为集合实例的ComboBox.ItemTemplate,我会看看我是否无法追踪源以提供示例但你明白了。 –