Reputation: 2211
I have a problem with binding multiple Lists to a ListBox. I want that every List has a different DataTemplate with a different color.
I have following model classes
public class Users
{
public Members Members{ get; set; }
}
public class Members
{
public List<string> Moderators { get; set; }
public List<string> Viewers { get; set; }
}
I have following ViewModel with INotifyPropertyChanged
private Users users;
public Users Users
{
get { return users; }
set
{
users= value;
RaisePropertyChanged("Users");
}
}
And I'm binding to this ListBox
<ListBox ItemsSource="{Binding Users.Members.Viewers}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now I only have that one List bound to the ListBox. It works great but I want the other list also bound to the same ListBox. Besides that I want that Moderators have a different template.
I tried many different things but nothing seemed to work.
Upvotes: 1
Views: 1624
Reputation: 31721
Instead of removing the names from the origination object why not keep it and specify different colors based off of the originating class?
Besides that I want that Moderators have a different template.
If you only have strings that is impossible. Remember the listbox ultimately sees only one list; so in one list, how is it possible to tag a string as either moderator or viewer?
a different DataTemplate with a different color.
If there are only strings I suggest you create wrapper classes, one for moderators and one for viewers, then project the strings into those classes to be held. Then you can follow my suggestion/example below.
Via the use of the Composite collection to hold different items (or one could actually use a base class list or a interface list if the instances have that commonality) and then have specialized data templates which look for the originating class, it can be done.
I have two classes one named Ships
and one named Passage
. Note that both classes both have a Name
property, but one could use something other than Name
for either or both in the templates.
Below I define the data templates and my listbox.
<Grid>
<Grid.Resources>
<DataTemplate DataType="{x:Type c:Ship}">
<TextBlock Text="{Binding Path=Name}"
Foreground="Red" />
</DataTemplate>
<DataTemplate DataType="{x:Type c:Passage}">
<TextBlock Text="{Binding Path=Name}"
Foreground="Blue" />
</DataTemplate>
</Grid.Resources>
<ListBox Name="myListBox"
Height="300"
Width="200"
ItemsSource="{Binding MyCompositeCollection}">
</ListBox>
</Grid>
So what will happen is that my ships will be red and the passages will be blue.
Here is my code in the VM:
private CompositeCollection _MyCompositeCollection;
public CompositeCollection MyCompositeCollection
{
get { return _MyCompositeCollection; }
set { _MyCompositeCollection = value; OnPropertyChanged("MyCompositeCollection"); }
}
Here I load the composite collection:
var temp = new CompositeCollection();
Ships.ForEach(sh => temp.Add(sh));
Passages.ForEach(ps => temp.Add(ps));
MyCompositeCollection = temp;
Upvotes: 2
Reputation: 3448
WPF can set distinct template by using ItemTemplateSelector but it entails class to be diffrent in some way. Your type is string so it does not differ in any way. My hint is to create enum as follows
enum MemberType { Moderator, Viewer }
and following class:
class Person
{
public string Name{get;set;}
public MemberType Type{get;set;}
}
then change to this
public class Members
{
public List<Person> Moderators { get; set; }
public List<Person> Viewers { get; set; }
}
and eventually in ItemTemplateSelector
public class TemplateSelector : DataTemplateSelector
{
public DataTemplate ViewerDataTemplate;
public DataTemplate ModeratorDataTemplate;
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var member = item as Person;
switch (member.Type)
{
case MemberType.Moderator:
return ModeratorDataTemplate;
case MemberType.Viewer:
return ViewerDataTemplate;
}
return null;
}
}
Upvotes: 2