How insert Separator in a databound ComboBox

As you might already know, I’m a big fan of the Model-View-ViewModel pattern. I’m using it extensively on the current I’m working on at work. Today I had to face a simple problem that was tricky to solve.

In the application I’m building, I have a “Library panel”. This panel contains a set of items that are used in my application. Because the number of items can be very large, I decided to add a filter capability. Filtering to a collection is very straightforward once you get familiar with the ICollectionView interface. If you want more details about it, check out Marlon’s blog post about it.

To give the user the possibility to filter the items, I added a ComboBox control. Of course, because I’m using the MVVM pattern, I’m not creating the ComboBoxItem myself, the databinding mechanism of WPF handle this (to be precise, the databinding handles collecting the item, and the ComboBox handles the creation of the ComboBoxItem to wrap them…).

The problem

In my ViewModel, I create a ObservableCollection<string> property that I called “Categories”.Then, in my view (XAML), I databound the ComboBox’s ItemsSource property to this “Categories”. Ok, it works fine and took me about 10min to do it.

Now, I want to add separator between some ComboBoxItem… Hmmm, how should I do that… I cannot do combobox.Items.Add(something) anymore because the ItemsSource property is databound… Well, I could as something in my ViewModel, but what ?

My solution

I wanted to keep the logical information about where Separator are in the ViewModel. This is typically an example of something that should stays in the ViewModel. I decided to add an empty items in my ObservableCollection for every Separator I wanter to have in the view.

In the view, I set up an ItemContainerStyle for my ComboBoxItem. The tricky part is, how could I replace my ComboBoxItem with a Separator… Well actually, we can’t. But what we can do is to change the entire template of the ComboBoxItem when the content is empty:

        
            
                
            
                      

And voila ! It works fine and keeps the logic in the ViewModel. If you have any other idea about how we can solve this issue, please feel free to comment 🙂

17 thoughts on “How insert Separator in a databound ComboBox

  1. Bien vu !
    On pouvait aussi faire ça avec la propriété ItemTemplateSelector… mais c’est vrai que c’est classe de tout faire en XAML 😉

  2. If you don’t mind using the more general-purpose ObservableCollection instead of ObservableCollection, then you could simply add a Separator object in the binding source:

    DataContext = new ObservableCollection
    {
    “Catergory 1”,
    new Separator(),
    “Catergory 2”,
    “Catergory 3”,
    };

  3. Erratum:
    In post #3, should read
    “…general-purpose ObservableCollection<object> instead of ObservableCollection<string>…”

  4. I used the ComboBox.ItemTemplate property to achieve the same goal.
    This work fine as well, but your solution is better in my case : I can use the DisplayMemberPath property at the same time !!
    Thanks a lot 😉

  5. I almost forget …
    There is no need for HorizontalAlignment=”Stretch” IsEnabled=”False” in the Separator (at least with Framework 4.0).

  6. It was not obvious at first to me so I want to add for others that you need to specify the binding path that will have your “empty value” as such

    Hope that helps

  7. “But IMHO I prefer not to have any UI-related stuff in my ViewModel classes”

    doesn’t adding a blank item (that consitutes a separator anyway) fail to achieve this?

  8. I like your idea, and I would like to implement it. However, you use an ObservableCollection. What is I were using a collection of entities? How would you get a separator then?

    Thanks

  9. Kevin,

    I guess you need to transform the set of objects at some point to add the empty items. You don’t have to use an ObservableColleciton, anything which implements IEnumerable will work (but without support for changes notifications).

    Jeremy

  10. This solution doesn’t work properly. If you have lets say combobox and another textbox in your window, set the keyboard focus to the next textbox, then hit tab/shift+tab, which will select your combobox, and then pressing up/down, you can select the empty elements, because the combobox view isn’t created, and the combobox is selecting empty elements…

  11. Richard,

    I guess you are right. Maybe we could try setting IsHitTestVisible to false but I’m not sure that would do the trick. For this particular case I think we should change the selection when a separator item is selected. Maybe you can do that by registering on the SelectionChanged event or using an attached property to do the job.

  12. @Richard, @Jeremy:

    Adding IsEnabled=”False” to the setters should fix that issue.

Leave a Reply

Your email address will not be published. Required fields are marked *