TreeView中的WPF Heirachical DataTemplate

时间:2010-12-03 17:03:38

标签: c# wpf xaml treeview datatemplate

我正试图在WPF中了解Heirarchical DataTemplates和TreeViews并遇到一些麻烦。

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

这适用于在TreeView中我看到我的目录,它递归显示所有子目录,但我想看到的是目录和文件!我检查了模型,它肯定在某些子目录中有文件,但我在树中看不到它们。

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

由于

单次

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

1 个答案:

答案 0 :(得分:2)

再看看这个:

        <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下的属性File中获取其子项。你真正想要的是文件显示在每个目录下,所以你应该创建一个暴露目录和文件的新属性:

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并同时向其添加目录和文件条目,以添加到Files和Directories集合。

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