TreeView中的WPF Heirachical DataTemplate [英] WPF Heirachical DataTemplate in TreeView

查看:62
本文介绍了TreeView中的WPF Heirachical DataTemplate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解WPF中的Heirarchical DataTemplates和TreeViews并遇到一些麻烦.

I am trying to get my head around Heirarchical DataTemplates and TreeViews in WPF and am having some trouble.

我创建了一个仅具有TreeView的应用程序,形式如下,并为Directory对象和File对象定义了HierarchicalDataTemplate,然后将TreeView绑定到模型的Directories属性(ObservableCollection).

I have created an app with only a TreeView on the form as below and defined HierarchicalDataTemplate's for both a Directory object and a File object I then Bind the TreeView to the Directories property (ObservableCollection) of my model.

<Grid>
        <Grid.Resources>

            <HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Directories}">
                <TextBlock Text="{Binding Path=Name}"/>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="{x:Type local:File}" ItemsSource ="{Binding Files}">
                <TextBlock Text="{Binding Path=FileName}"/>
            </HierarchicalDataTemplate>
        </Grid.Resources>
        <TreeView Margin="12,12,0,12" Name="treeView1" HorizontalAlignment="Left" Width="204" >
            <TreeViewItem ItemsSource="{Binding Directories}" Header="Folder Structure" />
        </TreeView>
    </Grid>

这可以通过在TreeView中看到我的目录并递归显示所有子目录来实现,但是我想看到的是目录和文件!我检查了模型,并确定在某些子目录中有文件,但在树中看不到它们.

This works in that in the TreeView I see my directories and it recursively displays all sub directories, but what I want to see is Directories and Files! I've checked the model and it definately has files in some of the sub directories but I can't see them in the tree.

我不确定是我的模板是问题还是我的模型,所以我将它们全部都包括在内了!:-)

I'm not sure if it is my template that is the problem or my model so I have included them all! :-)

谢谢

OneShot

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();

    }


    private MainWindowViewModel _vm;

    public MainWindowViewModel VM
    {
        set
        {
            _vm = value;
            this.DataContext = _vm;
        }
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        var d = new Directory() { Name = "temp" };
        recurseDir("c:\\temp", ref d);

        VM = new MainWindowViewModel( new List<Directory>() { d } );            
    }

    private void recurseDir(string path, ref Directory dir)
    {
        var files = System.IO.Directory.GetFiles(path);
        var dirs = System.IO.Directory.GetDirectories(path);

        dir.Name = path.Substring(path.LastIndexOf("\\")+1);

        for (int i = 0; i < files.Length; i++)
        {
            var fi = new FileInfo(files[i]);
            dir.Files.Add(new File() { 
                FileName = System.IO.Path.GetFileName(files[i]), 
                DirectoryPath = System.IO.Path.GetDirectoryName(files[i]), 
                Size = fi.Length, 
                Extension= System.IO.Path.GetExtension(files[i]) 
            });

        }

        for (int i = 0; i < dirs.Length; i++)
        {
            var d = new Directory() { Name = dirs[i].Substring(dirs[i].LastIndexOf("\\")+1) };
            recurseDir(dirs[i], ref d);
            dir.Directories.Add(d);

        }

    }
}

-

 public class MainWindowViewModel
        : DependencyObject
    {


        public MainWindowViewModel(List<Directory> Dirs)
        {
            this.Directories = new ObservableCollection<Directory>( Dirs);
        }

        public ObservableCollection<Directory> Directories
        {
            get { return (ObservableCollection<Directory>)GetValue(DirectoriesProperty); }
            set { SetValue(DirectoriesProperty, value); }
        }

        public static readonly DependencyProperty DirectoriesProperty =
            DependencyProperty.Register("Directories", typeof(ObservableCollection<Directory>), typeof(MainWindowViewModel), new UIPropertyMetadata(null));

        public Directory BaseDir
        {
            get { return (Directory)GetValue(BaseDirProperty); }
            set { SetValue(BaseDirProperty, value); }
        }

        public static readonly DependencyProperty BaseDirProperty =
            DependencyProperty.Register("BaseDir", typeof(Directory), typeof(MainWindowViewModel), new UIPropertyMetadata(null));


    }

-

public class Directory
    {
        public Directory()
        {
            Files = new List<File>();
            Directories = new List<Directory>();
        }
        public List<File> Files { get; private set; }
        public List<Directory> Directories { get; private set; }
        public string Name { get; set; }
        public int FileCount
        {
            get
            {
                return Files.Count;
            }
        }
        public int DirectoryCount
        {
            get
            {
                return Directories.Count;
            }
        }
        public override string ToString()
        {
            return Name;
        }
    }

-

public class File
    {
        public string DirectoryPath { get; set; }
        public string FileName { get; set; }
        public string Extension { get; set; }
        public double Size { get; set; }
        public string FullPath
        {
            get
            {
                return System.IO.Path.Combine(DirectoryPath, FileName);
            }
        }
        public override string ToString()
        {
            return FileName;
        }
    }

推荐答案

再次查看一下:

        <HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Directories}">
            <TextBlock Text="{Binding Path=Name}"/>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type local:File}" ItemsSource ="{Binding Files}">
            <TextBlock Text="{Binding Path=FileName}"/>
        </HierarchicalDataTemplate>

您的意思是,如果遇到文件类型为 File 的对象,请使用文本块显示该对象,然后从 Files 属性的文件.您真正想要的是将文件显示在每个目录下,因此您应该创建一个新属性以同时显示目录和文件:

What you're saying is that if you encounter an object of type File, display it with a text block and get its children from a property Files under the File. What you really want is for the Files to show up under each Directory, so you should create a new property that exposes both Directories and Files:

public class Directory
{
    //...
    public IEnumerable<Object> Members
    {
        get
        {
            foreach (var directory in Directories)
                yield return directory;

            foreach (var file in Files)
                yield return file;
        }
    }
    //...
}

,然后您的模板变为:

    <HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Members}">
        <TextBlock Text="{Binding Path=Name}"/>
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type local:File}">
        <TextBlock Text="{Binding Path=FileName}"/>
    </DataTemplate>


更新:

实际上,如果您想为会员接收更改收藏夹的通知,上述内容是不够的.如果是这种情况,我建议创建一个新的ObservableCollection,并在其中添加Directory和File条目,同时添加到Files和Directories集合中.

Actually, the above is not sufficient if you want to receive collection changed notifications for the Members. If that's the case, I recommend creating a new ObservableCollection and adding Directory and File entries to it in parallel to adding to the Files and Directories collections.

或者,您可能希望重新考虑如何存储您的信息并将所有内容都放在一个集合中.然后,其他列表就是主集合的简单过滤视图.

Alternately, you may wish to reconsider how you store your information and put everything in a single collection. The other lists are then simply filtered views of the main collection.

这篇关于TreeView中的WPF Heirachical DataTemplate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆