Posted by: Zeeshan Amjad | August 15, 2012

Multi Columns Combo Box


I came across one simple application written in MS Access. In that application there is one combo box that display multiple columns when open. I tried to do the same thing in WPF and guess that it would be an easy task just define the data template for ItemTemplate. Here is my first attempt of this.

Code Snippet
<Window x:Class="WpfCombo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="Multi Column ComboBox" Height="300" Width="400">
    <Grid>
        <ComboBox Height="30" Margin="5" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Margin="2" Grid.Column="0" Text="{Binding Name}"/>
                        <TextBlock Margin="2" Grid.Column="1" Text="{Binding State}"/>
                        <TextBlock Margin="2" Grid.Column="2" Text="{Binding Population}"/>
                                        </Grid>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</Window>

 

This code in fact display multiple columns, but this is not exactly what I want. This code also display multiple column for selected item.Take a look at the screen shot of this.

MultiColumn_ComboBox_01

 

I want to display only one value as a selected value, but multiple columns when open the combo box. There are multiple ways to do this. The first solution came to my mind is doing condition template selection which we already did several time. But for that we have to create a new class. I was looking for a solution where I don’t have to create a new class, in other words if I can do this with XAML only.

I was thinking may be I can use both data template and control template together, one for the selected item and other for the items when we drop downed the combo box. And the closest I can get is ItemContainerStyle property. I define the control template of container, it means I define the control template when we open the combo box and define data template when we don’t open the combo box.

Here is my code to do this.

Code Snippet
<Window x:Class="WpfCombo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="Multi Column ComboBox" Height="300" Width="400">
    <Grid>
        <ComboBox Height="30" Margin="5" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Margin="2" Text="{Binding Name}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
            <ComboBox.ItemContainerStyle>
                <Style TargetType="{x:Type ComboBoxItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Margin="5" Grid.Column="0" Text="{Binding Name}"/>
                                    <TextBlock Margin="5" Grid.Column="1" Text="{Binding State}"/>
                                    <TextBlock Margin="5" Grid.Column="2" Text="{Binding Population}"/>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ComboBox.ItemContainerStyle>
        </ComboBox>
    </Grid>
</Window>

 

Here is complete C# code of the program.

Code Snippet
using System.Windows;
using System.Collections.ObjectModel;

namespace WpfCombo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ObservableCollection<City> cities = new ObservableCollection<City>();

        public MainWindow()
        {
            InitializeComponent();

            cities.Add(new City() { Name = "Boston", State = "MA", Population = 3000000 });
            cities.Add(new City() { Name = "Los Angeles", State = "CA", Population = 7000000 });
            cities.Add(new City() { Name = "Frederick", State = "MD", Population = 65000 });
            cities.Add(new City() { Name = "Houston", State = "TX", Population = 5000000 });

            DataContext = cities;
        }
    }

    class City
    {
        public string State
        { get; set; }

        public string Name
        { get; set; }

        public int Population
        { get; set; }
    }
}

 

Here is the output of the program.

MultiColumn_ComboBox_02


Responses

  1. Thanks for the very nice post.
    but I have a question.
    How about the string being returned by the Combobox.Seleteditem? It’s just returning the Name of Class city, not really the selected text. Would it be posible to get all the strings shown on the dropdown “selected “item?
    E.X. If I Select Boston, I must also be able to get the “MA” and “300000”

    Thank you

    • Hi rick

      Thanks to like the post. Please correct me if i misunderstood your question. If we get the SelectedItem then we will get the class of State and from where I can get rest of the information.

      Regards
      Zeeshan Amjad

  2. Hello Zeeshan,
    Nice article! I need to do the same but with datagrid combobox. I need to show a combo box in the datagrid with two or three values. Do you have any code that can help me out? How different would this be from the code you are showing here?
    Thanks so much, really appreciate your help!!

  3. […] we have different presentation in combo box and selected item by using ItemContinerStyle property here. In that example we display multiple column in combo box but display only one data when we select […]

  4. Hi zeeshan,
    Is it possible to show the column header in this.
    I want to display header for each column present in combobox.

    can u please help me.
    regards
    azar

  5. Excellent

    Thanking you Very Much

    • Thanks to like it.

  6. Hello Zeesha this helped me a lot!

    I have one question left – why the name-Property is not shown in the ComboBox when a Item was selected with IsEditable=true? If IsEditable=false everything works perfect.

    Thanks and Greetings
    hanz

  7. I just found the answer:
    http://www.shujaat.net/2010/08/wpf-editable-combobox-with-datatemplate.html

    Greetings
    hanz


Leave a comment

Categories