显示Silverlight的ComboBox组头

时间:2013-10-31 17:06:26

标签: c# silverlight xaml combobox optgroup

我想在Silverlight中显示ComboBox OPTGROUP样式标题gruopings。我发现的每个网站(包括关于SO的问题)都会将此链接转换为过时的链接,并且很方便地显示我无法使用的代码片段。

E.g:

enter image description here

那我该怎么做?

3 个答案:

答案 0 :(得分:1)

查看我的类似问题:How to show group header for items in Silverlight combobox? 我将虚拟条目放在集合源中以指示组标题,然后修改DataTemplate以不同方式显示组标题和以不同方式显示正常条目。

答案 1 :(得分:1)

这是一种通用的方法。它不错,应该足够灵活 - 虽然它有一个弱点,需要扩展的集合类(不能使用CollectionViewSource)。

Grouped ComboBox screenshot

第1步 ComboBoxGroupHeader对象

这起着"虚拟进入" @NiteshChordiya提到。

public class ComboBoxGroupHeader
{
    public ComboBoxGroupHeader(object header)
    {
        Header = header;
    }

    public object Header { get; protected set; }
}

第2步 扩展的ComboBox

这会覆盖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"条目。这个实现基本上是只读的(如果你试图添加新项目,分组就会中断),但是支持" Add"," Insert"等操作会很简单。

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>

要使分组生效,源必须使用&#34; GroupedCollection&#34;以上,以包括虚拟标题项。例如:

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")
        });
    }
}

答案 2 :(得分:0)

ComboBox不支持组头。使用DataGrid实现它的替代方法或使用TreeView显示分组数据。

但是,您可以尝试这样的事情,

Silverlight Custom ComboBox