How to create two HierarchicalDataTemplates which are mutually-referential in Silverlight?
-
25-09-2019 - |
Question
Given that:
- DataTemplates cannot be assigned by TargetType
- StaticResource references can only reference previously
How does one template the following situation in a TreeView?
class Resource {
public string Name {get;}
public IEnumerable<Property> Properties {get;}
}
class Property {
public string Name {get;}
public IEnumerable<Resource> Values {get;}
}
That structure lends itself well to a tree which would look like:
Resource 1
|- Property A
| - Resource 2
| - Resource 3
|- Property B
|- Resource 4
This would trivial to template in WPF because of the TargetType
property of HierarchicalDataTemplate
. In Silverlight, we would have to do something more like:
<HierarchicalDataTemplate x:Key="ResourceTemplate"
ItemSource="{Binding Properties}"
ItemTemplate={StaticResource PropertyTemplate}" />
<HierarchicalDataTemplate x:Key="PropertyTemplate"
ItemSource="{Binding Values}"
ItemTemplate="{StaticResource ResourceTemplate}" />
Which obviously can't work because ResourceTemplate
can't reference PropertyTemplate
because it is defined after it in the XAML document. So, how do you solve this chicken-and-egg problem?
Solution
The only reasonable solution I've found is to create a third ViewModel type which would wrap either of the first two types (Resource or Property) and provide common properties to bind to: (e.g. children). This still is not very optimal, though, if the two types need very different templates because at that point, I am using the VisualStateManager
to switch between templates for the data.
<HierarchicalDataTemplate x:Key="TreeItemTemplate"
ItemSource="{Binding Children}">
<ContentPresenter Content="{Binding}">
<VisualStateManager.Groups>
<VisualStateGroup>
<VisualState Name="IsResource">
<!-- set resource template -->
</VisualState>
<VisualState Name="IsProperty">
<!-- set property template -->
</VisualState>
</VisualStateGroup>
</VisualStateManager.Groups>
</ContentPresenter>
</HierarchicalDataTemplate>