【问题标题】:HierarchicalDataTemplate.DataType is interface, how to implement 2 levels of TreeViewHierarchicalDataTemplate.DataType 为接口,如何实现2级TreeView
【发布时间】:2013-07-22 05:22:10
【问题描述】:

我知道如何通过将 HierarchicalDataTemplate.DataType 定义为 2 个 concreate 类来实现 2 个级别的 TreeView。我还发现了一些关于将 HierarchicalDataTemplate.DataType 定义为接口的主题,例如: WPF HiercharchicalDataTemplate.DataType: How to react on interfaces? Any way to use interfaces with wpf HierarchicalDataTemplate

但是我在TreeView中有两个层次:文件夹和文件,它是由两个接口收缩的:IFolder和IFile。 当我创建嵌套的 TreeViewItems 时,会引发 TargetInvocationException。但是只创建一层TreeViewItem就可以了。

这是代码: (可以在这里下载整个 VS2010 解决方案(下载后将扩展名从 png 重命名为 zip): http://img.bbs.csdn.net/upload/201307/23/1374565982_74852.png )

MainWindow.xaml:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:ItemTemplateSelector x:Key="ItemTemplateSelector">
        <local:ItemTemplateSelector.FolderTemplate>
            <HierarchicalDataTemplate DataType="{x:Type local:IFolder}" ItemsSource="{Binding Items}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Name}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </local:ItemTemplateSelector.FolderTemplate>
        <local:ItemTemplateSelector.FileTemplate>
            <HierarchicalDataTemplate DataType="{x:Type local:IFile}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Name}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </local:ItemTemplateSelector.FileTemplate>
    </local:ItemTemplateSelector>
</Window.Resources>
<Grid>
    <TreeView Name="tvwFiles" ItemTemplateSelector="{DynamicResource ItemTemplateSelector}" />
</Grid>

class ItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate FolderTemplate { get; set; }
    public DataTemplate FileTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        IFolder folder = item as IFolder;
        if (folder != null)
        {
            return FolderTemplate;
        }

        IFile file = item as IFile;
        if (file != null)
        {
            return FileTemplate;
        }

        return null;
    }
}


public interface IFolder
{
    string Name { get; set; }
}


public interface IFile
{
    string Name { get; set; }
}


public class Folder : IFolder
{
    public string Name { get; set; }

    public ICollection<object> Items
    {
        get
        {
            ICollection<object> items = new List<object>();

            if (SubFolders != null)
            {
                foreach (var folder in SubFolders)
                    items.Add(folder);
            }

            if (Files != null)
            {
                foreach (var file in Files)
                    items.Add(file);
            }

            return items;
        }
    }

    public ICollection<IFolder> SubFolders { get; set; }
    public ICollection<IFile> Files { get; set; }

    public Folder(string name)
    {
        Name = name;
    }
}


public class File : IFile
{
    public string Name { get; set; }

    public File(string name)
    {
        Name = name;
    }
}


public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        ObservableCollection<object> dirs = new ObservableCollection<object>();
        Folder folder = new Folder("Root");
        dirs.Add(folder);
        for (int i = 0; i < 3; ++i)
        {
            Folder subfolder = new Folder("Folder" + i);
            for (int j = 0; j < 3; ++j)
            {
                File File = new File("File" + j);
                subfolder.Files.Add(File);
            }
            folder.SubFolders.Add(subfolder);
        }

        tvwFiles.ItemsSource = dirs;
    }
}

【问题讨论】:

    标签: c# wpf interface hierarchicaldatatemplate datatemplateselector


    【解决方案1】:

    我发现了问题。

    public Folder : IFolder
    {
        ...
        public ICollection<IFolder> SubFolders { get; set; }
        public ICollection<IFile> Files { get; set; }
    }
    

    应该是:

    public Folder : IFolder
    {
        ...
        private ICollection<IFolder> _subFolders = new ObservableCollection<IFolder>();
        public ICollection<IFolder> SubFolders
        {
            get { return _subFolders; }
            set { _subFolders = value; }
        }
    
        private ICollection<IFile> _files = new ObservableCollection<IFile>();
        public ICollection<IFile> Files
        {
            get { return _files; }
            set { _files = value; }
        }
        ...
    }
    

    我只是没有为他们新建一个实例。


    顺便说一句:DataTemplateSelector 是接口 DataType 所必需的。

    【讨论】:

      【解决方案2】:

      我相信您可能以错误的方式看待这个问题。使用HierarchicalDataTemplate 声明父层中的数据类型,最重要的是,声明包含子项的属性。将其视为设置数据结构。

      然后您可以简单地使用普通的附加DataTemplates 来设置将使用的不同数据类型的样式。如果您在Resources 部分中声明DataTemplates,没有为它们指定键,那么它们将自动影响该类型的所有对象。

      我编写了一个文件同步应用程序并将其样式设置为类似于 Windows 资源管理器,我相信您正在尝试做类似的事情。但是,我不需要为我的文件和文件夹对象使用任何接口。它们每个都有一个Type 属性,我可以使用我编写的FileTypeConverter 将其绑定到Image.Source 属性,以显示各种类型的文件图标。

      我设计了一个DataTemplate 来呈现文件,另一个用于文件夹,一个HierarchicalDataTemplate 使用HierarchicalDataTemplate.ItemContainerStyle 属性定义每个项目的结构和容器。不幸的是,我目前无法访问该项目,因此无法提供更多代码示例。

      或者,这里有一些相关文章:

      Set TreeView HierarchicalDataTemplate with 2 levels in WPF

      WPF TreeView HierarchicalDataTemplate - binding to object with multiple child collections

      【讨论】:

      • 使用接口类作为 DataTemplate.DataType 与创建类不同,这是我问题的重点。对于concreate classes的情况,效果很好,没有问题。
      • 对于接口类,WPF不起作用,所以我引入了一个基于DataTemplateSelector的类ItemTemplateSelector来根据concreate对象进行DataTemplate选择。由于服务器端和客户端之间的接口隔离原则,我必须使用接口类而不是创建类。确实2级没必要用HierarchicalDataTemplate,只要DataTemplate就可以了,但这不是重点。
      • 我根据您的提示尝试了很多方法,但没有找到答案。如果你有VS2010+,你想从上面的链接下载我的源代码并尝试解决问题吗?非常感谢您的帮助。
      猜你喜欢
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-10
      • 2010-10-10
      • 1970-01-01
      相关资源
      最近更新 更多