2013-10-31 52 views
3

我想在Silverlight中显示ComboBox以及OPTGROUP样式的标题横幅。我发现每个网站(包括关于SO的问题)都可以将此链接粘贴到一个过时的链接上,并且很方便地不显示任何代码片段供我使用。显示Silverlight的组合框标题

例如为:

enter image description here

那么,如何做到这一点?

+0

这些项目是静态的还是像集合绑定的? –

+0

他们将是一个绑定集合 – Chris

+0

我可以发誓我过去通过将HeaderedItemsControl放置为集合实例的ComboBox.ItemTemplate,我会看看我是否无法追踪源以提供示例但你明白了。 –

回答

1

以下是一种通用方法。这并不坏,应该足够灵活 - 尽管它有需要扩展集合类的弱点(不能使用CollectionViewSource)。

Grouped ComboBox screenshot

步骤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") 
     }); 
    } 
} 
+1

请注意:尽管控件将“IsHitTestVisible”设置为false,但仍可通过键盘选择标题项目。您需要重写'OnKeyDown'并检查箭头键和向上翻页 - 要么禁用它们,要么实现自定义索引更新逻辑。 – Impworks