如何在单个Silverlight TreeView节点中拥有多种类型的子节点?

Jam*_*ber 5 c# silverlight treeview xaml hierarchicaldatatemplate

短途:

我必须显示TreeView不同类型的项目的层次结构(),并且不确定如何在Silverlight中干净地执行此操作.在WPF中,可以直接HierarchicalDataTemplate根据类型定义templates(),但Silverlight中不提供此功能.在Silverlight中,您必须将相同的模板应用于特定节点的所有子节点,因此您最终会得到一个单一的怪物模板,它可以处理每个可能类型的节点,应用于每个节点.

长版(带示例):

为了给出一个更具体(但是做作)的例子,考虑各种文件夹中的档案树视图,其中每个档案可以包含照片,歌曲和其他档案.每个文件夹可能包含多个子文件夹和存档.

|-Folder
  |-Folder
    |-Folder
      |-Archive
        | Photo1
        | Photo2
        | Song1
        | Song2
        |-Archive
          | Photo1
          | Song1
  |-Archive
    | Photo1
    | Photo2
    | Photo3
Run Code Online (Sandbox Code Playgroud)

树中的每种类型(文件夹,存档,照片,歌曲)的显示方式都不同.显而易见的解决方案似乎是HierarchicalDataTemplate为每种类型的项目创建一个.不幸的是,我找不到一个好方法,因为你似乎必须为node(ItemsSource={Binding ...}, ItemsTemplate={StaticResource TemplateForAllChildren})的所有子节点指定一个模板类型.

此要求导致模板滚雪球...存档可以将照片,歌曲和档案作为子项.由于必须将单个模板应用于所有子项,因此该模板必须能够处理照片,歌曲和档案.同样,文件夹的模板必须能够处理文件夹和档案,而档案模板现在卡在其中的照片和歌曲,所以它最终成为一个可以处理照片,歌曲,档案和文件夹的巨型模板.随着更多类型的添加,它们也会被集中到一个巨大的模板中.

有没有办法干净地完成这项工作,而不会累积一个巨型模板(和相关的节点视图模型),因为不同的类型被添加到树中?

谢谢!

一些澄清:

感谢到目前为止的答案,但我认为他们可能会让我回到最初的问题.我可能误解了答案.

考虑TreeView显示:

对于歌曲:带有艺术家/标题的滚动文本框和播放按钮

对于图片:缩略图图像和星级评分控件

对于存档:存档图像,其中一个进度条显示压缩

对于文件夹:显示文件夹名称的普通标签

据我所知,实现这一目标的唯一方法是拥有一个包含滚动文本框,播放按钮,缩略图查看器,星形控件,图像控件,进度条和标签的巨型HierarchicalDataTemplate.然后,我只是选择性地隐藏除了实际应用于节点的一个或两个控件之外的所有控件.

在WPF中,我可以将模板与节点类型相关联,因此每个节点都可以使用适当的模板.我想知道在Silverlight中是否有办法做到这一点.

再次感谢!

as-*_*cii 3

那么,你为什么不尝试这样的事情呢?

分层数据模板

<sdk:HierarchicalDataTemplate x:Key="ChildTemplate" ItemsSource="{Binding Path=SubItems}">
    <TextBlock Text="{Binding Name}" Foreground="{Binding ForegroundColor}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="FilesDataTemplate" ItemsSource="{Binding Path=SubItems}" ItemTemplate="{StaticResource ChildTemplate}">
    <TextBlock Text="{Binding Name}" Foreground="{Binding ForegroundColor}" />
</sdk:HierarchicalDataTemplate>
Run Code Online (Sandbox Code Playgroud)

节点类

public class Node
{
    public string Name { get; set; }
    public ObservableCollection<Node> SubItems { get; set; }
    public SolidColorBrush ForegroundColor { get; set; }

    public Node(string name, Color foregroundColor, params Node[] items)
    {
        this.Name = name;
        this.SubItems = new ObservableCollection<Node>(items);
        this.ForegroundColor = new SolidColorBrush(foregroundColor);
    }
}
Run Code Online (Sandbox Code Playgroud)

示例数据

public partial class MainPage : UserControl
{
    public ObservableCollection<Node> Nodes { get; set; }

    public MainPage()
    {
        InitializeComponent();

        this.Nodes = new Node("Root", Colors.Blue,
                             new Node("File1", Colors.Black),
                             new Node("File2", Colors.Black),
                             new Node("Archive1", Colors.Red,
                                        new Node("File3", Colors.Magenta),
                                        new Node("File4", Colors.Magenta))
                             ).SubItems;

        treeView1.DataContext = this;
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的情况下,也许可以帮助一个接口(例如 INode),该接口具有用于样式节点(如 ForegroundColor 或其他)的所有属性,这些属性将由每种类型的子类(存档、照片、音乐)实现。

希望这可以帮助。