Reputation: 11255
I'd like to visualize a collection of Test
class (POCO from model assembly) in a TreeView
. Each Test
instance has got a collection of Readers
and Groups
:
Test class pseudo code
public class Test
{
// properties
public ObservableCollection<Reader> Readers { get; set; }
public ObservableCollection<Group> Groups { get; set; }
}
What I want
My goal is to visualize the tests in a TreeView
like that:
Test 1
|- Reader 1
|- Reader 2
|- Group 1
|- Group 2
Test 2
|- Reader 1
|- Group 4
|- Group 5
What I got so far
I can show tests and readers by using a HierarchicalDataTemplate
<HierarchicalDataTemplate DataType="{x:Type model:Test}" ItemsSource="{Binding Readers}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
Basically I want to tell the TreeView
, "Hey there is another child item source with another template in my test class, use it!".
I tried using a CompositeCollection
of readers and groups, but got stuck because I don't want to change the Test class (it is generated code).
Upvotes: 0
Views: 323
Reputation: 9827
Create a Converter
and use it in your HierarchicalDataTemplate.ItemsSource
.
Converter :
public class ReadersGroupsCombineConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<Reader> readers = (value as Test).Readers;
ObservableCollection<Group> groups = (value as Test).Groups;
ObservableCollection<object> readersGroups = new ObservableCollection<object>();
foreach (Reader reader in readers)
readersGroups.Add(reader);
foreach (Group group in groups)
readersGroups.Add(group);
return readersGroups;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML :
<HierarchicalDataTemplate x:Key="HDTReaderGroups" ItemsSource="{Binding ., Converter={StaticResource ReaderGroupsCombineCnvKey}}">
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
Upvotes: 1
Reputation: 744
What I've done in the past, and recommend you to do, is to create a wrapper object for each type you want to represent in the treeview. You can initialize that structure in the viewmodel. When you have all your objects set up, you can do this:
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type Model:TestNode}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
And now the templates for the children:
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type Model:ReaderNode}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type Model:GroupNode}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
This way you will have a template for each type of object you are modeling.
As I've said before, I recommend you to do this, because a binding to an object that doesn't implement INotifyPropertyChanged leaks memory, and usually POCOs and DTOs don't implement it. You can see more here: https://support.microsoft.com/en-us/kb/938416
Upvotes: 0