Table of Contents
Item Template Selector

EO.Wpf ComboBox can use a DataTemplateSelector object to apply different templates to different items. This sample displays a list of "items" represented with the following class:

// A simple list item that has a name and a flag indicating
// whether it's a category or a product
private class ListItem
{
    private string m_szName;
    private bool m_bIsCategory;

    public ListItem(string name, bool isCategory)
    {
        m_szName = name;
        m_bIsCategory = isCategory;
    }

    public string Name { get { return m_szName; } }

    public bool IsCategory { get { return m_bIsCategory; } }
}

Two different DataTemplate are declared in the Window's Resources, one for "category" item, and one for "product" item:

XAML
<Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:eo="http://schemas.essentialobjects.com/wpf/"
        Title="MainWindow" Height="250" Width="350">
    <Window.Resources>
        <!-- DataTemplate for Category Item -->
        <DataTemplate x:Key="CategoryTemplate">
            <TextBlock IsEnabled="False" FontWeight="Bold" Text="{Binding Name}"></TextBlock>
        </DataTemplate>
        <!-- DataTemplate for Product Item -->
        <DataTemplate x:Key="ProductTemplate">
            <TextBlock Margin="10,0,0,0" Text="{Binding Name}"></TextBlock>
        </DataTemplate>
    </Window.Resources>
    <StackPanel>
        <eo:ComboBox x:Name="cbProducts" Width="200" HorizontalAlignment="Left">
        </eo:ComboBox>
    </StackPanel>
</Window>

Note the IsEnabled property of the root element of the category template is set to False. This automatically disables all category items.

A DataTemplateSelector class is created to select between these two templates based on whether the data item's IsCategory is true:

private class TemplateSelector : DataTemplateSelector
{
    //Keep the owner Window for resource lookup
    private Window m_Owner;

    public TemplateSelector(Window owner)
    {
        m_Owner = owner;
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        ListItem listItem = item as ListItem;
        if (listItem != null)
        {
            if (listItem.IsCategory)
                return m_Owner.FindResource("CategoryTemplate") as DataTemplate;
            else
                return m_Owner.FindResource("ProductTemplate") as DataTemplate;
        }

        return null;
    }
}

The following code is then used to initialize the ComboBox:

//Create the items
ListItem[] items = new ListItem[]
{
    new ListItem("Hardwares", true),
        new ListItem("The New iPad", false),
        new ListItem("Windows Surface", false),
        new ListItem("Kindle Fire", false),
        new ListItem("Chromebook", false),
    new ListItem("Softwares", true),
        new ListItem("Windows 8", false),
        new ListItem("Adobe Photoshop 11", false),
        new ListItem("QuickBooks 2013", false),
};

//Set the template selector. Here "this" is the Window object
cbProducts.ItemTemplateSelector = new TemplateSelector(this);

//Populate the ComboBox
cbProducts.ItemsSource = items;

The above code produces the following result:

Note the product items are indented due to the Margin applied in the product template. Also all category items are disabled due to the root element in the category template is disabled.