简体   繁体   English

TreeView 中的 WPF Heirachical DataTemplate

[英]WPF Heirachical DataTemplate in TreeView

I am trying to get my head around Heirarchical DataTemplates and TreeViews in WPF and am having some trouble.我试图了解 WPF 中的 Heirarchical DataTemplates 和 TreeViews,但遇到了一些麻烦。

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.我在表单上创建了一个只有 TreeView 的应用程序,如下所示,并为 Directory 对象和 File 对象定义了 HierarchicalDataTemplate,然后将 TreeView 绑定到我的模型的 Directory 属性 (ObservableCollection)。

<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>

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!这是因为在 TreeView 中我看到我的目录并递归显示所有子目录,但我想看到的是目录和文件! 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!我不确定是我的模板有问题还是我的模型有问题,所以我把它们都包括在内了! :-) :-)

Thanks谢谢

OneShot 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;
        }
    }

Take a look at this again:再看看这个:

        <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>

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 .你的意思是,如果你遇到一个File类型的对象,用一个文本块显示它,并从File下的属性Files获取它的子项。 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;
        }
    }
    //...
}

and then your template becomes:然后你的模板变成:

    <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>

UPDATE:更新:

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.如果是这种情况,我建议创建一个新的 ObservableCollection 并向其中添加目录和文件条目,同时添加到文件和目录集合。

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.其他列表则是主集合的简单过滤视图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM