【问题标题】:WPF Treeview bind to multiple, nested listsWPF Treeview 绑定到多个嵌套列表
【发布时间】:2013-12-06 07:31:42
【问题描述】:

我有下面的递归数据结构,我想将它绑定到树视图。但我不知道如何指定我的数据模板/分层数据模板。

public class MediaContent
{
    public MediaContent()
    {
        this.Sequences = new List<MediaSequence>();
        this.Items = new List<MediaItem>();
    }

    public List<MediaSequence> Sequences
    {
        get;
        set;
    }

    public List<MediaItem> Items
    {
        get;
        set;
    }        
}

public class MediaSequence
{
    public MediaSequence()
    {
        this.Sequences = new List<MediaSequence>();
        this.Items = new List<MediaItem>();
    }

    public List<MediaSequence> Sequences
    {
        get;
        set;
    }

    public List<MediaItem> Items
    {
        get;
        set;
    }
}

public class MediaItem
{
    public string Filename
    {
        get;
        set;
    }
}

困难在于每个节点可以包含2个列表,并且列表是递归的。示例数据如下所示。

var uberNestedSequence = new MediaSequence();
uberNestedSequence.Items.Add(new MediaItem { Filename = "video1.mp4" });
uberNestedSequence.Items.Add(new MediaItem { Filename = "video2.avi" });

var nestedSequence = new MediaSequence();
nestedSequence.Sequences.Add(uberNestedSequence);

var nestedSequence2 = new MediaSequence();

this.Media.Sequences.Add(nestedSequence);
this.Media.Sequences.Add(nestedSequence2);

那么,如何在 WPF 树视图中显示这些数据?

<TreeView Margin="5" VerticalAlignment="Top" Grid.Row="1" ItemsSource="{Binding Media}">

我已尝试以下方法,但显然您不能为同一数据类型指定 2 个不同的模板。

<HierarchicalDataTemplate DataType="{x:Type local:MediaSequence}" ItemsSource="{Binding Sequences}">
    <TextBlock Text="sequence" />
</HierarchicalDataTemplate>

<HierarchicalDataTemplate DataType="{x:Type local:MediaSequence}" ItemsSource="{Binding Items}">
    <TextBlock Text="item" />
</HierarchicalDataTemplate>

感谢任何帮助,谢谢

【问题讨论】:

  • 您将拥有 MediaSequence 或 MediaItem 类型的树,但您的树中不能同时拥有这两种树。
  • 如果使用 TemplateSelector 会起作用吗???

标签: wpf recursion treeview datatemplate


【解决方案1】:

好的,让我们先从最简单的方面来解决这个问题,它应该有助于理清思路。它可能看起来不像,但没有什么比我们通常看到的普通文件夹和文件结构更复杂的了。

所以如果我们先从树的末端开始,我们可以定义

<DataTemplate DataType="{x:Type local:MediaItem}">
  <TextBlock Text="item" />
</DataTemplate>

我们没有任何子项目,所以它只是一个普通的模板。

深入到树中,我们现在有了MediaSequences 的节点,其中既有项目又有序列。如果我们能把它们当作一件事呢?

好吧,如果我们坚持文件系统类比,您会发现 DotNet 将 FileInfos 和 DirectoryInfos 定义为基数 FileSystemInfo 的派生。我们需要做的都是一样的。

public interface IMedia
{
  // Actually they have nothing in common
}

public class MediaItem : IMedia
{
  ...
}

public class MediaSequence : IMedia
{
  public IEnumerable<IMedia> Children 
  {
    get
    {
      // This one collection can now expose both types
      // but can be anything behind the scenes
      return Sequences.Concat(Items);
    }
  }
}

这允许我们定义另一个模板

<HierarchicalDataTemplate DataType="{x:Type local:MediaSequence}" ItemsSource="{Binding Children}">
  <TextBlock Text="sequence" />
</HierarchicalDataTemplate>

如果你真的需要,你也可以将你的根定义为不同的东西,但它实际上只是一个序列。

public class MediaContent : MediaSequence
{
   ...
}

【讨论】:

  • 这很好用,非常感谢。我只需要更改 children 属性以首先将每个列表强制转换为 IMedia,然后再调用 concat 方法,否则它不会编译。我当然可以将列表更改为 IMedia 类型,但我更喜欢明确的类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
相关资源
最近更新 更多