Answered by:
Binding Two Collections to One Combobox

Question
-
Hello,
I want to bind two different Collections to the same combobox at the same time. Each set needs to have a header obove the group. But I can not find a way to get this to work properly. It should look like the following.
Set onefrist item set one
second item set one
Set twofirst item set two
second item set two
This must be done in a combobox, i hope you can help with thisWednesday, April 22, 2009 2:05 PM
Answers
-
Hi,
As far as I know, in order to achieve the group style for a ItemsControl, the data should be in the same collection view. Not in a CompositeCollection which composite the two(or more) different collections. If you want to create group in the same collection, you can handily use the CollectionViewSource like this:
<CollectionViewSource x:Key="CollectionPerson"
Source="{StaticResource perserCollectionKey}">
<CollectionViewSource.GroupDescriptions>
<dat:PropertyGroupDescription PropertyName="ID" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
And then set the GroupStyle:
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<!--your visual respresentation here-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
If you really want to achieve the layout like you provided, you can set two ListBoxs in the ComboBox, and bind the collection to each ListBox respectively. The following is a small exampel.
XAML code:
<Window x:Class="WpfComboBoxTest.Window6"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfComboBoxTest"
xmlns:dat="clr-namespace:System.Windows.Data;assembly=PresentationFramework"
Title="Window6" Height="300" Width="300">
<Window.Resources>
<local:PersonCollection x:Key="perserCollectionKey" />
<local:AnimalCollection x:Key="animalCollectionKey" />
<!--Person-->
<DataTemplate DataType="{x:Type local:Person}">
<Border>
<TextBlock Text="{Binding Name}" />
</Border>
</DataTemplate>
<!--Animal-->
<DataTemplate DataType="{x:Type local:Animal}">
<Border>
<TextBlock Text="{Binding Description}" />
</Border>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ComboBox Name="comboBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="Person collection" Grid.Row="0" Grid.Column="0" />
<TextBlock Text="Person collection" Grid.Row="2" Grid.Column="0" />
<ListBox ItemsSource="{Binding Source={StaticResource perserCollectionKey}}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
<ListBox ItemsSource="{Binding Source={StaticResource animalCollectionKey}}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>
</ComboBox>
</StackPanel>
</Window>
In the code behind:
using System.Windows;using System.Collections.ObjectModel;
namespace WpfComboBoxTest
{
public partial class Window6 : Window
{
public Window6()
{
InitializeComponent();
}
}
public class PersonCollection : ObservableCollection<Person>
{
public PersonCollection()
{
this.Add(new Person() { Name = "Person1", ID = "Person" });
this.Add(new Person() { Name = "Person2", ID = "Person" });
}
}
public class AnimalCollection : ObservableCollection<Animal>
{
public AnimalCollection()
{
this.Add(new Animal() { Description = "Animal1", ID = "Animal" });
this.Add(new Animal() { Description = "Animal2", ID = "Animal" });
}
}
public class Person
{
public string Name { get; set; }
public string ID { get; set; }
}
public class Animal
{
public string Description { get; set; }
public string ID { get; set; }
}
}
Hope this helps.
Thanks.
- Edited by Jim Zhou - MSFT Wednesday, April 29, 2009 7:53 AM modify the code
- Marked as answer by Jim Zhou - MSFT Wednesday, April 29, 2009 7:54 AM
Tuesday, April 28, 2009 7:49 AM
All replies
-
Hi,
As far as I know, in order to achieve the group style for a ItemsControl, the data should be in the same collection view. Not in a CompositeCollection which composite the two(or more) different collections. If you want to create group in the same collection, you can handily use the CollectionViewSource like this:
<CollectionViewSource x:Key="CollectionPerson"
Source="{StaticResource perserCollectionKey}">
<CollectionViewSource.GroupDescriptions>
<dat:PropertyGroupDescription PropertyName="ID" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
And then set the GroupStyle:
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<!--your visual respresentation here-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
If you really want to achieve the layout like you provided, you can set two ListBoxs in the ComboBox, and bind the collection to each ListBox respectively. The following is a small exampel.
XAML code:
<Window x:Class="WpfComboBoxTest.Window6"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfComboBoxTest"
xmlns:dat="clr-namespace:System.Windows.Data;assembly=PresentationFramework"
Title="Window6" Height="300" Width="300">
<Window.Resources>
<local:PersonCollection x:Key="perserCollectionKey" />
<local:AnimalCollection x:Key="animalCollectionKey" />
<!--Person-->
<DataTemplate DataType="{x:Type local:Person}">
<Border>
<TextBlock Text="{Binding Name}" />
</Border>
</DataTemplate>
<!--Animal-->
<DataTemplate DataType="{x:Type local:Animal}">
<Border>
<TextBlock Text="{Binding Description}" />
</Border>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ComboBox Name="comboBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="Person collection" Grid.Row="0" Grid.Column="0" />
<TextBlock Text="Person collection" Grid.Row="2" Grid.Column="0" />
<ListBox ItemsSource="{Binding Source={StaticResource perserCollectionKey}}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
<ListBox ItemsSource="{Binding Source={StaticResource animalCollectionKey}}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>
</ComboBox>
</StackPanel>
</Window>
In the code behind:
using System.Windows;using System.Collections.ObjectModel;
namespace WpfComboBoxTest
{
public partial class Window6 : Window
{
public Window6()
{
InitializeComponent();
}
}
public class PersonCollection : ObservableCollection<Person>
{
public PersonCollection()
{
this.Add(new Person() { Name = "Person1", ID = "Person" });
this.Add(new Person() { Name = "Person2", ID = "Person" });
}
}
public class AnimalCollection : ObservableCollection<Animal>
{
public AnimalCollection()
{
this.Add(new Animal() { Description = "Animal1", ID = "Animal" });
this.Add(new Animal() { Description = "Animal2", ID = "Animal" });
}
}
public class Person
{
public string Name { get; set; }
public string ID { get; set; }
}
public class Animal
{
public string Description { get; set; }
public string ID { get; set; }
}
}
Hope this helps.
Thanks.
- Edited by Jim Zhou - MSFT Wednesday, April 29, 2009 7:53 AM modify the code
- Marked as answer by Jim Zhou - MSFT Wednesday, April 29, 2009 7:54 AM
Tuesday, April 28, 2009 7:49 AM -
I was able to put the two collections in one collection so my problem is solved, the items have a header. thanks for the helpWednesday, April 29, 2009 8:30 AM