views:

598

answers:

2

Is there any way to make a DataTemplate reference itself just from XAML? In this particular case trying to reference a DataTemplate from a ListBox contained within the same DataTemplate. Here is the solution I'd like, which doesn't work.

  <DataTemplate x:Key="nestedItem" DataType="{x:Type local:NestedItem}">
    <Expander Header="{Binding Path=Name}">
      <ListBox ItemsSource="{Binding Path=Items}" x:Name="itemsList"
        ItemTemplate="{StaticResource nestedItem}"/>
    </Expander>
  </DataTemplate>

And here's the solution I am currently using, which works.

  <DataTemplate x:Key="nestedItem" DataType="{x:Type local:NestedItem}">
    <Expander Header="{Binding Path=Name}" Expanded="OnItemExpanded">
      <ListBox ItemsSource="{Binding Path=Items}" x:Name="itemsList"/>
    </Expander>
  </DataTemplate>

With code behind:

private void OnItemExpanded(object sender, RoutedEventArgs e)
  {
    if (e.OriginalSource != sender) return;
    var source = (Expander) sender;
    ListBox listBox = source.FindName("itemsList") as ListBox;
    NestedItem item = source.DataContext as NestedItem;
    listBox.ItemsSource = item.Items;
    listBox.ItemTemplate = (DataTemplate) FindResource("nestedItem");
  }
+1  A: 

If you change your inner reference to be a DynamicResource instead of a StaticResource then it will work as you want. This is because there are some differences in how a StaticResource and DynamicResource actually look for the Resource item.

<DataTemplate x:Key="Local_NestedItem"
     DataType="{x:Type local:NestedItem}">
 <Expander Header="{Binding Path=Name}">
  <ListBox ItemsSource="{Binding Path=Items}"
   x:Name="itemsList"
   ItemTemplate="{DynamicResource Local_NestedItem}" />
 </Expander>
</DataTemplate>

Also, if you don't mind using some code, another good option is to use a DataTemplateSelector

rmoore
I hadn't even tested out DynamicResource for some crazy reason, mistake on my part, but sure enough it works. I already had a DataTemplateSelector for some items in the collection which changes the template based on the type of object (it's a generic collection). Thanks!
Jeff Wain
A: 

Did you try using HierarchicalDataTemplate instead of DataTemplate for your first solution? Did not test it for your case, but for treeviews it usually works that way.

Simpzon
I did, the problem was with tabbing since the template contained TextBoxes and the users needed to be able to tab sequentially between the boxes themselves, not the TreeViewItems. It was taking way too much time to handle the TreeViewItem tab events.
Jeff Wain
I see, that navigation would indeed be annoying. Maybe it would work with some special treeview-control template, but you have a working solution anyway.
Simpzon