C# WPF Treeview和数据绑定目录树
我正在尝试实现一个目录树视图,该视图还显示MVVM项目中的所有文件。C# WPF Treeview和数据绑定目录树,c#,wpf,xaml,mvvm,treeview,C#,Wpf,Xaml,Mvvm,Treeview,我正在尝试实现一个目录树视图,该视图还显示MVVM项目中的所有文件。模型中的我的文件夹和文件结构如下所示: public class UserDirectory { private ObservableCollection<UserFile> files; private ObservableCollection<UserDirectory> subfolders; private String directoryPath; //public ge
模型中的我的文件夹和文件结构如下所示:
public class UserDirectory
{
private ObservableCollection<UserFile> files;
private ObservableCollection<UserDirectory> subfolders;
private String directoryPath;
//public getters and setters...
}
public class UserFile
{
private String filePath;
private Category category; //Archive, Document, Exe, etc...
//public getters and setters
}
public ObservableCollection<Object> RootDirectoryItems { get; }
= new ObservableCollection<object>();
但是我想重用我的类结构,因为我需要显示UserFile
的Category
数据
问题
在维护当前数据结构时,如何显示文件和子文件夹
(很抱歉,图像上传不起作用)XAML
<TreeView
ItemsSource="{Binding RootDirectoryItems}"
>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:UserDirectory}" ItemsSource="{Binding Items}">
<Label Content="{Binding Name}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:UserFile}">
<Label Content="{Binding Name}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
在C#中,假设所有属性设置器上都存在INotifyPropertyChanged
样板文件。我向UserDirectory
添加了两个属性:
Name
,一个只读属性,只返回DirectoryPath
的名称段。如果DirectoryPath
可能在运行时更改,则其设置程序应调用OnPropertyChanged(“名称”)
,这样查看Name
属性的绑定将知道需要获取新值UserFile
获得了一个类似的Name
属性,如果可能的话,它还附带了关于提升PropertyChanged
的相同建议
项
:同样是一个只读属性,如果其中一个组成集合发生更改,您应该适当地提高属性更改
(处理ICollectionChanged.CollectionChanged
,如果您有setter,则在setter中也要这样做)。绑定不关心属性的声明类型,因此它只返回System.Collections.IEnumerable
——它甚至可以返回对象
,XAML也不关心。但是,让我们足够具体,不要过于具体,以至于鼓励C#中的任何人尝试将该属性用于任何事情
如果是我,我几乎肯定会创建UserDirectory
和UserFile
裸不可变的“POCO”类,而不更改INotifyPropertyChanged
,如果磁盘上有任何更改,只需重新填充即可。如果我有理由期望目录会有很大的变化,我可能会通过给UserDirectory
一个FileWatcher
并让它自己重新填充来摆脱不变性
下面是C#:
谢谢!这是一个非常好的书面解释,我只有一些疑问。1) 我不明白RootDirectoryItems
的目的,我应该在这里确切地输入什么?2) 另外,使用子文件夹?.Cast().Union(文件)代码>我们基本上是将子文件夹
和文件
列表合并到项目
列表中,对吗?因为我有同样的想法,但试图用CollectionContainer
将它们放在ViewModel中,但不知道如何前进。1RootDirectoryItems
是用来填充树视图根目录的项UserDirectory
可能还有一些UserFile
。你以前是怎么填充它的?2.是的,这将生成所有子文件夹的结果枚举,后跟所有文件。您不需要任何花哨的东西,只需要这些对象的任何旧序列即可供TreeView枚举。事实上,我以前并没有填充它。我的ViewModel中有一个UserDirectory-rootDirectory
属性,它被赋予Worker
类类型以查找其文件和子文件夹。我可以在RootDirectoryItems
的get
中返回RootDirectoryItems
的项目吗?@RiccardoLomazzi。或者使RootDirectory
成为公共属性并绑定ItemsSource=“{Binding RootDirectory.Items}”
。一旦您编写了将目录枚举到UserDirectory
实例中的代码,只需使用UserDirectory
就可以了。非常感谢您的输入。我现在正在努力实现它。很难保持这种POCO结构,我想我只需要在UserFile和UserDirectory的属性上实现一个OnPropertyChanged(是的,我将来需要修改它们的路径)。但是那FileWatcher
引起了我的好奇心。。。
public ObservableCollection<Object> RootDirectoryItems { get; }
= new ObservableCollection<object>();
public class UserDirectory
{
public ObservableCollection<UserFile> Files { get; set; } = new ObservableCollection<UserFile>();
public ObservableCollection<UserDirectory> Subfolders { get; set; } = new ObservableCollection<UserDirectory>();
// Concat demands a non-null argument
public IEnumerable Items { get { return Subfolders?.Cast<Object>().Concat(Files); } }
public String DirectoryPath { get; set; }
public String Name { get { return System.IO.Path.GetFileName(DirectoryPath); } }
}
public class UserFile
{
public String FilePath { get; set; }
public Category Category { get; set; }
public String Name { get { return System.IO.Path.GetFileName(FilePath); } }
}
<TreeView
ItemsSource="{Binding RootDirectoryItems}"
>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Items}">
<Label Content="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>