Grouping items in a ComboBox

26,561

It is possible. Use a ListCollectionView with a GroupDescription as the ItemsSource and just provide a GroupStyle to your ComboBox. See sample below:

XAML:

<Window x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:StackOverflow"
        xmlns:uc="clr-namespace:StackOverflow.UserControls"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <ComboBox x:Name="comboBox">
            <ComboBox.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name}"/>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ComboBox.GroupStyle>
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>
</Window>

Code-behind:

namespace StackOverflow
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            //this.comboBox.DataContext = this;

            List<Item> items = new List<Item>();
            items.Add(new Item() { Name = "Item1", Category = "A" });
            items.Add(new Item() { Name = "Item2", Category = "A" });
            items.Add(new Item() { Name = "Item3", Category = "A" });
            items.Add(new Item() { Name = "Item4", Category = "B" });
            items.Add(new Item() { Name = "Item5", Category = "B" });

            ListCollectionView lcv = new ListCollectionView(items);
            lcv.GroupDescriptions.Add(new PropertyGroupDescription("Category"));

            this.comboBox.ItemsSource = lcv;
        }


    }

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

}
Share:
26,561

Related videos on Youtube

debe
Author by

debe

C# developer trying to figure out the wonderful world of WPF

Updated on April 19, 2020

Comments

  • debe
    debe about 4 years

    I have a ListView that contains two types of objects, single and multiple. The single is a ordinary TextBlock while the multiple is a ComboBox with items.

    I'm trying to group the items in the ComboBox without success. Is it possible? Or should I go for a different approach?

    What I'm trying to achieve:

    [ComboBox v]
        [Header  ]
        [    Item]
        [    Item]
        [Header  ]
        [    Item]
    
    • strattonn
      strattonn over 13 years
      Sounds more like a TreeView to me.
    • debe
      debe over 13 years
      I agree... I made a treeview first but the end user wants a combobox...
  • Tony
    Tony over 12 years
    Thank you for helping us with this! Helped a lot! God bless.
  • Bluety
    Bluety almost 9 years
    I tried your solution and it's works. But I can't get the selected value, I tried with combobox.SelectedItem.ToString() but it doesn't return the expected result. Do you have an idea ? thx
  • Sean
    Sean about 7 years
    Sorry for the two year delay Bluety, but I had a similar problem because my underlying property (string), didn't match the SelectedItem type (my Item class) and the binding never took place. Binding to SelectedValue instead of SelectedItem solved the problem
  • Sean
    Sean about 7 years
    Actually, binding to SelectedValue instead of SelectedItem can solve the problem but won't carry the group information. Changing the bound property type to the Item class fixed it.
  • Samuel LIOULT
    Samuel LIOULT about 7 years
    This answer seems to does not work in UWP. Is there a solution to do the same in a Windows 10 app? Thanks
  • Richard Moore
    Richard Moore over 6 years
    This is excellent. But I found it a bit confusing because the Header Template and Item Template both bind to a property called "Name". It'd be clearer if the Item.Name property was renamed to (say) Item.Description, and then in the XAML the Header Template would bind to the implicit "Name" property in the ListCollectionView, and the Item Template would bind to "Description". Great example nonetheless - thanks.
  • M Stoerzel
    M Stoerzel about 4 years
    Excellent answer. Binding ItemSource to an ObservableCollection<Item> would be the cherry on the cake :)
  • Pawcio
    Pawcio over 2 years
    I guess there is no way for the groups to be expandable, like in context menu?