2010-07-21 55 views
13

我有一类是这样的:递归DataTemplates可能吗?

public class Section 
{ 
    private IEnumerable<Section> sections; 
    private IEnumerable<KeyValuePair<string, string>> attributes 

    public string Name {get;set;} 
    public IEnumerable<Section> Sections 
    { 
     get {return sections;} 
    } 
    public IEnumerable<KeyValuePair<string, string>> Attributes 
    { 
     get {return attributes;} 
    } 

    public Section(...) 
    { 
     //constructor logic 
    } 
} 

这是包含在另一个类,让叫它OtherClass为了论证的缘故,环绕它和WPF使用在ObjectDataProvider的。

如您所见,Section的一个实例可以包含许多其他Section实例。

有没有办法在XAML中创建一个处理此递归的模板?

这是我到目前为止有:

<UserControl x:Class="OtherClassEditor" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:OtherClassNS="clr-namespace:NameSpace" 
    Height="300" Width="300"> 
    <UserControl.Resources> 
     <ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" /> 
     <DataTemplate x:Key="listViewAttr"> 
      <WrapPanel> 
       <TextBlock Text="{Binding Path=Key}"></TextBlock><TextBlock Margin="0,0,4,0">: </TextBlock> 
       <TextBlock Text="{Binding Path=Value}"></TextBlock> 
      </WrapPanel> 
     </DataTemplate> 
     <DataTemplate x:Key="listViewSection"> 
      <StackPanel> 
       <WrapPanel Margin="0,0,0,8"> 
        <TextBlock Margin="0,0,4,0">Section:</TextBlock> 
        <TextBlock Text="{Binding Path=Name}"/> 
       </WrapPanel> 
      </StackPanel> 
     </DataTemplate> 
     <DataTemplate x:Key="listViewData"> 
      <StackPanel> 
       <WrapPanel Margin="0,0,0,8"> 
        <TextBlock Margin="0,0,4,0">Section: </TextBlock> 
        <TextBlock Text="{Binding Path=Name}"/> 
        <ListView DataContext="{Binding Path=Sections}" ItemTemplate="{StaticResource listViewSection}" ItemsSource="{Binding Sections}"> 
        </ListView> 
        <ListView DataContext="{Binding Path=Attributes}" ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}"> 

        </ListView> 
       </WrapPanel> 
      </StackPanel>  
     </DataTemplate> 
    </UserControl.Resources> 
    <Grid> 
     <ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{StaticResource listViewData}" ItemsSource="{Binding Sections}"> 
     </ListView> 
    </Grid> 
</UserControl> 

但我不能让递归,作为DataTemplate只能引用一个是之前宣布。

这可以在XAML中完成吗?如果是这样,怎么样?这是我需要在代码后面做的事吗?

DataTemplates是否应该走?是否有更好的方式来显示和编辑这些数据?

+3

如果您使用DynamicResource而不是StaticResource,这是否工作?如果它有效,它会很有趣,但如果模板导致无限递归,我会讨厌看看会发生什么。 – 2010-07-21 14:01:35

+0

我没有想到这个!它确实有效,但我喜欢'HierarchicalDataTemplate'的外观。它似乎更适合用途。 – 2010-07-21 14:32:12

回答

2

也许我误解了你的情况,但是HierarchicalDataTemplate你在找什么?

+0

感谢您的提示,我现在正在阅读它。 – 2010-07-21 14:10:49

+0

HierarchicalDataTemplate仅适用于TreeView和MenuItem。我不知道为什么这是被接受的答案。 – 2017-01-09 17:54:02

22

如果有人需要看看如何做到这一点,而无需使用HierarchicalDataTemplate

<UserControl x:Class="OtherClassEditor" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:OtherClassNS="clr-namespace:NameSpace" 
    Height="300" Width="300"> 
    <UserControl.Resources> 
     <ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" /> 
     <DataTemplate x:Key="listViewAttr"> 
      <WrapPanel> 
       <TextBlock Text="{Binding Path=Key}"></TextBlock> 
       <TextBlock Margin="0,0,4,0">: </TextBlock> 
       <TextBlock Text="{Binding Path=Value}"></TextBlock> 
      </WrapPanel> 
     </DataTemplate> 
     <DataTemplate x:Key="listViewData"> 
      <StackPanel> 
       <WrapPanel Margin="0,0,0,8"> 
        <TextBlock Margin="0,0,4,0">Section: </TextBlock> 
        <TextBlock Text="{Binding Path=Name}"/> 
       </WrapPanel> 
       <ListView ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}" /> 
       <ListView ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}" /> 
      </StackPanel>  
     </DataTemplate> 
    </UserControl.Resources> 
    <Grid> 
     <ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}"> 
     </ListView> 
    </Grid> 
</UserControl> 

这让我基本上我想要什么。

主要变化是Dan Bryant建议的:将ItemTemplate更改为对递归对象(Section)使用Dynamic而不是静态资源。