I'm working on a WPF project. I recently did a refactoring that put some of my model objects into wrappers. I've abridged the classes so they read nicely:
public class Wrapper
{
public AbstractModel Model;
}
public abstract class AbstractModel
{
public string DisplayName;
}
public class Parent : AbstractModel
{
public ObservableCollection<Wrapper> MyChildren;
}
public class Child : AbstractModel
{
//Nothing relevant to the issue (I think).
}
//a .xaml.cs file
public partial class MyPropertiesControl
{
//This is actually a dependency property that I bind to in other views, but I was too lazy to write the whole thing out.
public ObservableCollection<Wrapper> ItemsToDisplay { get; }
}
I want to display a TreeView that shows the collection of Wrappers and their (potential) children. Previously, there was no Wrapper class, just AbstractModel, Parent, and Child. It was quite simple to create the tree view in that case:
<TreeView ItemsSource="{Binding ElementName=Root, Path=ItemsToDisplay}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type Parent}" ItemsSource="{Binding MyChildren}">
<Label Content="{Binding DisplayName}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type Child}">
<Label Content="{Binding DisplayName}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
Now that the objects are in wrappers, I can't figure out how to write the templates. I tried a bunch of different things. These are two ideas I tried:
<TreeView ItemsSource="{Binding ElementName=Root, Path=ItemsToDisplay}">
<TreeView.Resources>
<DataTemplate DataType="{x:Type Wrapper}">
<ContentControl Content="{Binding Model}">
<ContentControl.Resources>
<HierarchicalDataTemplate DataType="{x:Type Parent}" ItemsSource="{Binding MyChildren}">
<Label Content="{Binding DisplayName}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type Child}">
<Label Content="{Binding DisplayName}"/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</TreeView.Resources>
</TreeView>
<TreeView ItemsSource="{Binding ElementName=Root, Path=ItemsToDisplay}">
<TreeView.Resources>
<DataTemplate DataType="{x:Type Wrapper}">
<ContentControl Content="{Binding Model}">
<ContentControl.Resources>
<HierarchicalDataTemplate DataType="{x:Type Parent}" ItemsSource="{Binding MyChildren}">
<HierarchicalDataTemplate.Resources>
<DataTemplate DataType="{x:Type Wrapper}">
<ContentControl Content="{Binding Model}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type Child}">
<Label Content="{Binding DisplayName}"/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</HierarchicalDataTemplate.Resources>
<Label Content="{Binding DisplayName}"/>
</HierarchicalDataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</TreeView.Resources>
</TreeView>
In both cases, I only see the first level of parents, I don't see any children. Not even the default class name that WPF will use when there isn't a defined template for that type, but the parent nodes actually show no children at all.
I added an event handler to the mouse dragging over the tree view and put a breakpoint on the event handler so I could make sure all the collections were populated (they were).
Has anyone else here bound wrapped objects to a tree view? How did you get all the data to display correctly?
I guess another potential issue is that getting to the wrapped object via ContentControls might not be the best idea. I'm not getting a code-smell vibe from it, but it is kind of annoying that I can't access the wrapped object in a cleaner way. If anyone has any ideas to remedy that, it may help with the TreeView issue.
