Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple item combo box with headers?

Is it possible to have "column headers" on a combo box bound to multiple items? For example a combo box that displays a persons name. The combo box would display John Doe. But I'd like to display column headers:

First   Last
John    Doe
Jane    Doe
Jimmy   Doe

Is this possible without the use of a data grid? What about a simple solution that includes the use of a data grid? I found one solution for embedding a data grid into a combo box but it looks difficult and requires MS Blend.

I'd be happy if I could just get some headers as the first row in the drop down.

G

Here is my xaml code with HB's attempt that produces a compile error as mentioned in the comments.

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
<ComboBox Name="cboPlaceNames" Grid.IsSharedSizeScope="True" ItemsSource="{DynamicResource items}" Height="22" Width="285" Margin="0,6,165,0" SelectedIndex="0" HorizontalAlignment="Right" VerticalAlignment="Top" SelectionChanged="cboPlaceNames_SelectionChanged">
  <ComboBox.Resources>
    <CompositeCollection x:Key="items">
      <ComboBoxItem IsEnabled="False">
        <Grid TextElement.FontWeight="Bold">
          <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A"/>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition SharedSizeGroup="B"/>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition SharedSizeGroup="C"/>
          </Grid.ColumnDefinitions>
          <Grid.Children>
            <TextBlock Grid.Column="0" Text="Name"/>
            <TextBlock Grid.Column="2" Text="CLLI"/>
            <TextBlock Grid.Column="4" Text="Street"/>
          </Grid.Children>
        </Grid>
      </ComboBoxItem>
      <Separator/>
      <CollectionContainer Collection="{Binding Source={x:Reference cboPlaceNames}, Path=DataContext.Data}"/>
    </CompositeCollection>

    <DataTemplate DataType="x:Type obj:PlaceName">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition SharedSizeGroup="A"/>
          <ColumnDefinition Width="5"/>
          <ColumnDefinition SharedSizeGroup="B"/>
          <ColumnDefinition Width="5"/>
          <ColumnDefinition SharedSizeGroup="C"/>
        </Grid.ColumnDefinitions>
        <Grid.Children>
          <TextBlock Grid.Column="0" Text="{Binding Name}"/>
          <TextBlock Grid.Column="2" Text="{Binding CLLI}"/>
          <TextBlock Grid.Column="4" Text="{Binding Street}"/>
        </Grid.Children>
      </Grid>
    </DataTemplate>
  </ComboBox.Resources>
</ComboBox>      
like image 799
GAR8 Avatar asked Apr 27 '11 17:04

GAR8


3 Answers

I liked Nandha's answer because this was what I was trying to achieve. However, the text field of the combo box will not work correctly.

Since I am lazy, to get around this I created a StackPanel of Horizontal orientation, with a TextBox bound to a field from the selected item, and the Combo Box with the embedded ListView. The Combo Box now has a width of 20 so just the down arrow shows (you can play with the width and margins to get just the right look. This makes the text box look like a combo box, with all the benefits of the ListView, and much less coding.

I hope this helps.enter image description here

like image 100
user2378757 Avatar answered Nov 15 '22 12:11

user2378757


Example:

<ComboBox Name="cb" Grid.IsSharedSizeScope="True" ItemsSource="{DynamicResource items}">
    <ComboBox.Resources>
        <CompositeCollection x:Key="items">
            <ComboBoxItem IsEnabled="False">
                <Grid TextElement.FontWeight="Bold">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="A"/>
                        <ColumnDefinition Width="5"/>
                        <ColumnDefinition SharedSizeGroup="B"/>
                    </Grid.ColumnDefinitions>
                    <Grid.Children>
                        <TextBlock Grid.Column="0" Text="Name"/>
                        <TextBlock Grid.Column="2" Text="Occupation"/>
                    </Grid.Children>
                </Grid>
            </ComboBoxItem>
            <Separator/>
            <CollectionContainer Collection="{Binding Source={x:Reference cb}, Path=DataContext.Data}"/>
        </CompositeCollection>

        <DataTemplate DataType="{x:Type obj:Employee}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="A"/>
                    <ColumnDefinition Width="5"/>
                    <ColumnDefinition SharedSizeGroup="B"/>
                </Grid.ColumnDefinitions>
                <Grid.Children>
                    <TextBlock Grid.Column="0" Text="{Binding Name}"/>
                    <TextBlock Grid.Column="2" Text="{Binding Occupation}"/>
                </Grid.Children>
            </Grid>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>

Note that getting the Collection-binding right is not that easy because there is neither DataContext nor VisualTree to rely on, ElementName and RelativeSource does not work, this is because CompositeCollection is just a collection, not a FrameworkElement.

Other than that the way this is done is via Grids that have shared size columns. The DataTemplate is applied automatically via the DataType.

screenshot

Edit: Setting the header-ComboBoxItem's IsHitTestVisible property to False is not enough since it still can be selected using the keyboard. I now changed it to IsEnabled="False" which fades out the item a bit. You could probably re-template that item to not do that. Or if you find another way of disabling it from selection that would of course work out too.

like image 30
H.B. Avatar answered Nov 15 '22 12:11

H.B.


The simplest way to add columns headers to combobox is to use listview in combobox. The following code is give the solution to it.

            <ComboBox HorizontalAlignment="Center" 
                      IsTextSearchEnabled="False" Width="200"                                            
                      IsEditable="True" Text="{Binding }"> 
                 <ListView ItemsSource="{Binding YOURITEMSOURCE}" 
                        SelectedItem="{Binding Path=SELECTEDITEMSOURCE}"
                         Height="200" ScrollViewer.VerticalScrollBarVisibility="Visible">                  
                           <ListView.View>
                               <GridView>
                                  <GridViewColumn Width="130"  Header="Name" DisplayMemberBinding="{Binding Name}"   />
                                  <GridViewColumn Width="130" Header="Occupation" DisplayMemberBinding="{Binding Occupation}" />
                                  <GridViewColumn Width="130"  Header="Age" DisplayMemberBinding="{Binding Age}" />
                                  <GridViewColumn Width="130" Header="Salary" DisplayMemberBinding="{Binding Salary}" />
                               </GridView>
                           </ListView.View>
                  </ListView>

            </ComboBox>
like image 34
Nandha kumar Avatar answered Nov 15 '22 10:11

Nandha kumar