I am trying to render a TreeView with a mix of self-referencing and external entities but cannot find any solution that works..
I have the following models:
# Folder
-> string Name
-> Folder ParentFolder
-> Collection<Folder> Children
-> Collection<Document> Documents
# Document
-> string Name
-> Folder Folder
I'm trying to display it as a file system hierarchy like this:
+ Folder 1
+ Folder 1.1
- Doc 1
- Doc 2
+ Folder 2
+ Folder 2.1
+ Folder 2.2
- Doc 3
- Doc 4
The ViewModel bound to the view contains a Collection<Folder> Folders
.
I've tried a lot of different combination in the XAML with simple binding and MultiBinding but without success..
Here is my current XAML (which doesn't work because not displaying the hierarchy):
<TreeView ItemsSource="{Binding Folders}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type model:Folder}">
<HierarchicalDataTemplate.ItemsSource>
<MultiBinding>
<Binding Path="Children" />
<Binding Path="Documents" />
</MultiBinding>
</HierarchicalDataTemplate.ItemsSource>
<TextBlock Text="{Binding Name}" Background="Blue"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type model:Document}">
<TextBlock Text="{Binding Name}" Background="Red"/>
</DataTemplate>
</TreeView.Resources>
</TreeView>
I've also tried the following that displays the folders hierarchy but not the documents (which is I think due to not specifying the Documents
property anywhere in the XAML but not sure how..):
<TreeView ItemsSource="{Binding Folders}">
<TreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type model:Folder}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type model:Document}">
<TextBlock Text="{Binding Name}" Background="Red"/>
</DataTemplate>
</TreeView.Resources>
</TreeView>
Thank you for your help!
Your current XAML should work if you just define and use a converter that creates a composite collection of folders and documents:
public class Converter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
IEnumerable<object> folders = values[0] as IEnumerable<object>;
IEnumerable<object> docs = values[1] as IEnumerable<object>;
if (folders != null && docs != null)
return Enumerable.Concat(folders, docs);
else if (folders != null)
return folders;
else if (docs != null)
return docs;
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
}
XAML:
<TreeView ItemsSource="{Binding Folders}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type model:Folder}">
<HierarchicalDataTemplate.ItemsSource>
<MultiBinding>
<MultiBinding.Converter>
<model:Converter />
</MultiBinding.Converter>
<Binding Path="Children" />
<Binding Path="Documents" />
</MultiBinding>
</HierarchicalDataTemplate.ItemsSource>
<TextBlock Text="{Binding Name}" Background="Blue"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type model:Document}">
<TextBlock Text="{Binding Name}" Background="Red"/>
</DataTemplate>
</TreeView.Resources>
</TreeView>