Share via


Insert ComboBox Item Separator Which is Filled Through Data Binding

As title says, this article discusses how to add item separator in combo box which is populated using data binding.

We will create a simple combo box in xaml as shown below with Binding to Items on DataContext source. 

 <ComboBox Height="40" ItemsSource="{Binding Items}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Item}" />
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>

 
And Data model used to populate this combo box

public class ComboBoxModelItem
    {
        public string Item { get; set; }
    }


    public class ComboBoxDataModel
    {
        public List<ComboBoxModelItem> Items { get; set; }
        public ComboBoxDataModel()
        {
            Items = new List<ComboBoxModelItem>();
            Items.Add(new ComboBoxModelItem() { Item ="Item 1" });
            Items.Add(new ComboBoxModelItem() { Item = "Item 2" });
            Items.Add(new ComboBoxModelItem() { Item = "Item 4" });
            Items.Add(new ComboBoxModelItem() { Item = "Item 6"  });

        }
    }

and in page/control constructor 

            this.DataContext = new ComboBoxDataModel();

Above code will simply create a combo box with four items with no separator.
Now we will modify the above code so that we can include a separator and further whether there will be separator is also pulled through Data Binding

To do this we introduce a simple flag on Data Model IsSelectable which will control whether item will act or behave as separator through ItemContainerStyleSelector. 
Yes ItemContainerStyleSelector is final piece of puzzle which will define a how selector will behave based on IsSelectable flag.

To do this we will update the combo box xaml like this (changes highlighted) and also add a static resource 

 <Page.Resources>        
        <local:SelectOrNotSelectStyleSelecter x:Key="comboItemStyleSelector"/>        
    </Page.Resources>

<ComboBox Height="40" ItemsSource="{Binding Items}" ItemContainerStyleSelector="{StaticResource comboItemStyleSelector}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Item}" />
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>

Data model and dummy data inside to 

public class ComboBoxModelItem
    {
        public string Item { get; set; }
        public bool IsSelectable { get; set; } 
    }


    public class ComboBoxDataModel
    {
        public List<ComboBoxModelItem> Items { get; set; }
        public ComboBoxDataModel()
        {
            Items = new List<ComboBoxModelItem>();
            Items.Add(new ComboBoxModelItem() { Item ="Item 1", IsSelectable = true });
            Items.Add(new ComboBoxModelItem() { Item = "Item 2", IsSelectable = true });
            Items.Add(new ComboBoxModelItem() { Item = "-------------", IsSelectable = false });
            Items.Add(new ComboBoxModelItem() { Item = "Item 4", IsSelectable = true });
            Items.Add(new ComboBoxModelItem() { Item = "-------------", IsSelectable = false });
            Items.Add(new ComboBoxModelItem() { Item = "Item 6", IsSelectable = true });

        }
    }

Finally we will derive the class StyleSelector(see link for more details) to implement our custom selection logic as shown below. 

 public class SelectOrNotSelectStyleSelecter : StyleSelector
    {
        protected override Style SelectStyleCore(object item, DependencyObject container)
        {
            bool isSelectable = (item as ComboBoxModelItem).IsSelectable;
            Style style = new Style(typeof(ComboBoxItem));
            style.Setters.Add(new Setter(UIElement.IsHitTestVisibleProperty, isSelectable));
            return style;
        }
    }

Basically in above code we create a Style for ComboBoxItem target type and set the IsHitTestVisibleProperty to the IsSelectable flag which is queried using item object passed to SelectStyleCore function. 
IsSelectable will be false in case item is not selectable and will make IsHitTestVisible also false, in turn preventing user to select the item. 

 Question exact details here.