我想在 Silverlight中显示ComboBox
带有样式的标题组。OPTGROUP
我发现的每个网站(包括关于 SO 的问题)都将这个链接指向一个过时的链接,并且方便地显示没有代码片段供我使用。
例如:
那么我该怎么做呢?
我想在 Silverlight中显示ComboBox
带有样式的标题组。OPTGROUP
我发现的每个网站(包括关于 SO 的问题)都将这个链接指向一个过时的链接,并且方便地显示没有代码片段供我使用。
例如:
那么我该怎么做呢?
请参阅我的类似问题:如何在 Silverlight 组合框中显示项目的组标题? 我将虚拟条目放在集合源中以指示组头,然后修改 DataTemplate 以不同的方式显示组头,并以不同的方式显示正常条目。
这是一种通用方法。这还不错,而且应该足够灵活——尽管它有需要扩展集合类的弱点(不能使用 CollectionViewSource)。
步骤 1 ComboBoxGroupHeader 对象
这起到了@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;
}
}
}
Step 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”,以便包含虚拟标题项。例子:
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")
});
}
}