显示Silverlight的组合框标题 [英] Show ComboBox group header for Silverlight

查看:302
本文介绍了显示Silverlight的组合框标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Silverlight中显示 ComboBox OPTGROUP 样式标题。



例如:

我发现的每个网站(包括SO的问题)都会将此链接拖放到过时的链接, / p>

>



那么我该如何做呢?

解决方案

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





步骤1 ComboBoxGroupHeader对象



这起到了@NiteshChordiya提到的虚拟条目的作用。

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

public object Header {get;保护集; }
}

第2步 / em>



这将覆盖 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元素,对象项)
{
base.PrepareContainerForItemOverride(element,item);
var container = element as ComboBoxItem;
if(container!= null&& item is ComboBoxGroupHeader)
{
//防止选择
container.IsHitTestVisible = false;

//调整容器以显示标题内容
container.ContentTemplate = HeaderTemplate
container.Content =((ComboBoxGroupHeader)item).Header;
}
}
}

/ strong> 扩展集合类



这样做了分组,并添加了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;
}

private static IEnumerable< object> GetGroupedItems(IEnumerable< T> items,Func< T,TGroup> grouping)
{
return item
.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 =9TextDecorations =UnderlineForeground =DarkGray
Text ={Binding}/>
< / local:GroupedComboBox.HeaderTemplate>
< / local:GroupedComboBox>

要使分组生效,源必须使用上述GroupedCollection伪标题项。示例:

  public class Item 
{
public string Name {get;组; }
public string Category {get;组; }

public Item(string name,string category)
{
Name = name;
Category = category;
}
}

public class Item:GroupedCollection< Item,string>
{
public Items(IEnumerable< Item> items)
:base(items,item => item.Category){}
}

public class ViewModel
{
public IEnumerable< Item>源{get;私人集}

public ViewModel()
{
Source = new Items(new Item [] {
new Item(Apples,Fruits),
new Item(Carrots,Vegetables),
new Item(Bananas,Fruits),
new Item(Lettuce,Vegetables),
新项目(Oranges,Fruits)
});
}
}


I want to show a ComboBox with OPTGROUP style header gruopings in Silverlight. Every website I find (including questions on SO) that sovle this link to an outdated link and, handily, show no code snippets for me to work from.

E.g.:

So how do I do this?

解决方案

Here is one generalized approach. It's not bad, and should be flexible enough -- although it has the weakness of requiring an extended collection class (cannot make use of CollectionViewSource).

Step 1 ComboBoxGroupHeader object

This plays the role of "dummy entry" mentioned by @NiteshChordiya.

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

    public object Header { get; protected set; }
}

Step 2 Extended ComboBox

This overrides PrepareContainerForItemOverride, in order to tinker with the dummy items' containers. It also provides an (optional) "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 Extended collection class

This does the grouping, and adds the dummy "ComboBoxGroupHeader" entries. This implementation is essentially read-only (groupings would break if you tried to add new items), but it would be straight-forward to support operations like "Add", "Insert", etc.

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

Usage

It works like a normal ComboBox, with the optional HeaderTemplate:

<local:GroupedComboBox ItemsSource="{Binding Source}">
    <local:GroupedComboBox.HeaderTemplate>
        <TextBlock FontSize="9" TextDecorations="Underline" Foreground="DarkGray"
                   Text="{Binding}" />
    </local:GroupedComboBox.HeaderTemplate>
</local:GroupedComboBox>

For the grouped to take effect, the source must use the "GroupedCollection" above, so as to include the dummy header items. Example:

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

这篇关于显示Silverlight的组合框标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆