I am trying to bind an object that has two collection and those collection has its own hierarchy below it. I want to bind that object to tree control so that the two different collections appear at the same level in the tree.
Here is an example
public class Organization |
{ |
public List<People> Peeps { get; set; } |
public List<Equipment> Equip { get; set; } |
} |
I want People and Equipment to appear at the same level in the tree. Is there a way to do it even if Organization is not at the top level of the hierarchy?
6 Answers, 1 is accepted
HierarchicalDataTemplate
Peeps
Peep 1
Peep 2
Equip
Equip 1
Equip 2
...
Sorry (in advance) for the quick response…very busy. I am assuming you know how to use Telerik’s HierarchicalDataTemplate.
Step 1) Create a DataTemplateSelector in the Telerik.Windows.Controls namespace:
namespace projectNamespace |
{ |
public class TreeNodeTemplateSelector : DataTemplateSelector |
{ |
public DataTemplate PeepsTemplate { get; set; } |
public DataTemplate EquipTemplate { get; set; } |
public override DataTemplate SelectTemplate(object item, DependencyObject container) |
{ |
if (item != null) |
{ |
if (item is Peep) |
{ |
return PeepsTemplate; |
} |
else if (item is Equip) |
{ |
return EquipTemplate; |
} |
} |
return null; |
} |
} |
} |
Step 2 optional) Create an interface in your view model. This will be used to aggregate the two collections into one.
namespace projectNamespace |
{ |
public interface IOrgTreeNode |
{ |
} |
} |
Step 3) Create a combined collection in the parent object that combines the two collections. If you did not create an interface you could use ‘object’ Note you could probably create a fancy LINQ query here but this is down and dirty.
private ObservableCollection<IOrgTreeNode> _treeNodes; |
public ObservableCollection<IOrgTreeNode> TreeNodes |
{ |
get |
{ |
if (_treeNodes == null) |
{ |
_treeNodes = new ObservableCollection<IOrgTreeNode>(); |
foreach (Peep p in _peeps) |
{ |
_treeNodes.Add(p); |
} |
foreach (Equip e in _equips) |
{ |
_treeNodes.Add(e); |
} |
} |
return _treeNodes; |
} |
} |
Step 4) In Xaml set up your hierarchy templates. Keep in mind order matters in Xaml, if you need to reference a resource it must be before it in xaml. That is why template selector comes after the two data templates it needs :
<Grid.Resources> |
<telerikCore:HierarchicalDataTemplate x:Key="_peepNode"> |
<StackPanel Orientation="Horizontal"> |
<TextBlock Text="{Binding Path=Description}" VerticalAlignment="Center" /> |
</StackPanel> |
</telerikCore:HierarchicalDataTemplate> |
<telerikCore:HierarchicalDataTemplate x:Key="_equipNode"> |
<StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Description}" VerticalAlignment="Center" /> |
</StackPanel> |
</telerikCore:HierarchicalDataTemplate> |
<local:TreeNodeTemplateSelector x:Key="TreeNodeTemplateSelector" PeepsTemplate="{StaticResource _peepNode}" EquipTemplate="{StaticResource _equipNode}" /> |
<telerikCore:HierarchicalDataTemplate x:Key="_orgNode" ItemsSource="{Binding Path=TreeNodes}" ItemTemplateSelector="{StaticResource TreeNodeTemplateSelector}"> |
<StackPanel Orientation="Horizontal"> |
<TextBlock Text="{Binding Path=OrgName}" VerticalAlignment="Center" /> |
</StackPanel> |
</telerikCore:HierarchicalDataTemplate> |
</Grid.Resources> |
Notes: There may be a better way to do this but this is what I came up with and it serves my purpose.
Organization Name
Peep Node
Peep Node
Equip Node
Equip Node
I'm trying to get
Organization Name
Peeps
Peep Node
Peep Node
Equip
Equip Node
Equip Node
Guess I can create an object that "houses" the respective collection but was trying to do it without throwing more containing objects into the viewmodel. Ex: Organization has collection of ChildHolder, PeepChildHolder exposes Peeps collection, EquipChildHolder exposes Equip collection.