Nested XAML Treeview Structure with mixed object types


Nested XAML Treeview Structure with mixed object types



So I've been working on a complex treeview structure using WPF binding. None of the scenarios I've found online have been able to solve the issue, but they have come close.



So I have three objects that look something this:


public class A
{
public string Name {get; set;}
public List<A> ListOfA {get; set;}
public List<B> ListOfB {get; set;}
}

public class B
{
public string Name {get; set;}
public List<C> ListOfC {get; set;}
public List<D> ListOfD {get; set;}
}

public class C
{
public string Name {get; set;}
public List<D> {get; set;}
}

public class D
{
public string Name{get; set;}
}



It should be noted that the ListOfA, ListOfB, ListOfC, and ListOfD can all be empty. I know this seems convoluted, but it makes perfect sense for my application as to why I'd be doing it this way.



Below is an example of what the treeview could look like


A - Name
| - A - Name
| - B - Name
| - D - Name
| - D - Name
| - D - Name
| - A - Name
| - B - Name
| - C - Name
| - D - Name
| - D - Name
| - A - Name
| - A - Name
| - A - Name
| - A - Name
| - A - Name



So I figured out how to format a treeview of A and B with something like below in the A class.


public IList Children
{
get
{
return new CompositeCollection()
{
new CollectionContainer() { Collection = ListOfA },
new CollectionContainer() { Collection = ListOfB }
};
}
}
}



Which I got from this question: WPF Treeview Databinding Hierarchal Data with mixed types



Below is my XAML code, substituting real objects with A/B/C. Note ListOfA is a view model member.


<TreeView ItemsSource = "{Binding Children}">
<TreeView.Resources>

<HierarchicalDataTemplate DataType="{x:Type local:A}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>

<HierarchicalDataTemplate DataType="{x:Type local:B}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>

</TreeView.Resources>
</TreeView>



This works great, but what I can't figure out is how to functionally add D to this tree view. I've been able to do it by adding a tree view item, with a nested tree view to contain the ListOfD inside the HierarchicalDataTemplate for type B, but I know that isn't a good way to do it.



I also tried adding something like:


<DataTemplate DataType={x:Type local:D>
<TextBlock Text={Binding Name}/>
</DataTemplate>



But this doesn't work, I assume because not every child of that 'Children' object doesn't have any object of type D inside of it. I'm also not sure how to handle the object of type C, but I'm more focused on D right now, and willing to bet I'll know how to handle it once I get D working anyways.



Am I making this harder than it needs to be, or was I on the right track with nesting things within the Hierarchical Data Template?




1 Answer
1



C just needs a template that looks like


<HierarchicalDataTemplate DataType="{x:Type local:C}" ItemsSource="{Binding ListOfD}">
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>



so you'd end of up with:


<HierarchicalDataTemplate DataType="{x:Type local:A}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:B}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:C}" ItemsSource="{Binding ListOfD}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplateDataType="{x:Type local:D}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>



and your classes:


public class A
{
public string Name {get; set;}
public List<A> ListOfA {get; set;}
public List<B> ListOfB {get; set;}
public IList Children
{
get
{
return new CompositeCollection()
{
new CollectionContainer() { Collection = ListOfA },
new CollectionContainer() { Collection = ListOfB }
};
}
}
}

public class B
{
public string Name {get; set;}
public List<C> ListOfC {get; set;}
public List<D> ListOfD {get; set;}
public IList Children
{
get
{
return new CompositeCollection()
{
new CollectionContainer() { Collection = ListOfC },
new CollectionContainer() { Collection = ListOfD }
};
}
}
}

public class C
{
public string Name {get; set;}
public List<D> ListOfD {get; set;}
}

public class D
{
public string Name{get; set;}
}





Oops, meant to ask about how to handle D, but I'll be sure to add that!
– knkokout64
Jun 29 at 19:23





Oh, if DataTemplate isn't working, change it to HierarchicalDataTemplate and don't specify an ItemsSource
– Joel Lucsy
Jun 29 at 19:27





Wow, I really was over complicating it, thanks! The only issue I'm having now is that members of D are appearing under B, but not under objects of type C.
– knkokout64
Jun 29 at 19:39






Oh, uh, I see I missed the binding of the Text in C, it should be <TextBlock Text="{Binding}"/> i'll modify my answer.
– Joel Lucsy
Jun 29 at 19:41






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Export result set on Dbeaver to CSV

Opening a url is failing in Swift