WPF 绑定列表视图复选框以显示为收藏夹
WPF Binding listview checkboxes to display as favorites
在我当前的 WPF MVVM 设置中,我有一个从 files/folders 目录填充的树视图。包括子文件夹和文件。但是我想实现一个简单的 'favorites' 功能。这意味着我可以单击树视图中每个文件的复选框,然后当我单击主 'checkbox in the UI' 时,它将过滤列表以仅显示 'favorties'.
这似乎是一个普遍的问题,但我该怎么做呢?组织和绑定 UI?
我已将解决方案 'visual studio 2013' 发布到我的保管箱,以供愿意帮助我的任何人使用。
Download Dropbox Files
我的猜测是添加另一个 ObservableCollection,它存储被选中的节点和原始树视图节点。因此,当用户启用主复选框时,它会将收藏夹列表加载到 ui,当未选中时,它会重新加载树视图。
// collection of nodes which you see in the image below on the left
public ObservableCollection<INode> DisplayNodes //nodes displayed in UI
public ObservableCollection<INode> FavoriteNodes //nodes marked as favorites
public ObservableCollection<INode> StructureNodes //system node structure
下面的伪函数
public void PopulateUI()
{
DisplayNodes.Clear();
if (showFavorites.isChecked)
{
DisplayNodes = FavoriteNodes;//nodes displayed in UI
}else{
DisplayNodes = StructureNodes;
}
}
我无法从工作中下载您的项目,但我可以就此为您提供一些一般指导。
这可以通过修改您的 INode 实现(FileNode、DirectoryNode 等)以包含 IsFavorite
bool 属性.
来完成
在您的视图模型中,添加一个名为 FavoritesEnabled
的 属性。在 属性 的 setter 中,您可以将 RootNodes
可观察对象 collection 替换为 collection 过滤 INode。
private bool favoritesEnabled;
public bool FavoritesEnabled
{
get
{
return this.favoritesEnabled;
}
set
{
this.favoritesEnabled = value;
this.RootNodes = value == true
? new ObservableCollection(this.FilterFavorites)
: new ObservableCollection(this.CreateRootNodes);
}
}
private IEnumerable<INode> FilterFavorites()
{
List<INode> nodes = new List<INode>();
foreach(DirectoryNode directory in this.RootNodes.OfType<DirectoryNode>())
{
nodes.AddRange(this.filterFavorites(nodes, directory.Children.OfType<DirectoryNode>());
nodes.AddRange(this.RootNodes.OfType<FileNode>().Where(item => item.IsFavorite);
}
}
private List<INode> FilterFavorites(List<INode> filteredResults, IEnumerable<DirectoryInfo> directories)
{
// Recursively look up all favorites.
foreach(DirectoryNode directory in directories)
{
filteredResults.AddRange(FilterFavorites(filteredResults, directory));
}
nodes.AddRange(this.RootNodes.OfType<FileNode>().Where(item => item.IsFavorite);
return filteredResults;
}
然后您只需更新树视图的数据模板,以便每个项目的复选框 data-bound 到 INode 实现上的 IsFavorite 属性。
上面的递归代码或多或少是伪造的,因为我无法在不关闭您的项目的情况下对其进行测试。它应该可以帮助您朝着正确的方向开始。使用这种方法,您可以继续只维护一个 collection。您需要将 RootNodes
属性 的创建移出您的构造函数并移至可重用方法中。这样,当您在视图模型中切换收藏夹 属性 时,您的 RootNodes
collection 会生成收藏夹 collection 或 "all" collection.
如果你不能让它工作,我今晚可以从家里拿走你的东西并举一个适当的例子。
在我当前的 WPF MVVM 设置中,我有一个从 files/folders 目录填充的树视图。包括子文件夹和文件。但是我想实现一个简单的 'favorites' 功能。这意味着我可以单击树视图中每个文件的复选框,然后当我单击主 'checkbox in the UI' 时,它将过滤列表以仅显示 'favorties'.
这似乎是一个普遍的问题,但我该怎么做呢?组织和绑定 UI?
我已将解决方案 'visual studio 2013' 发布到我的保管箱,以供愿意帮助我的任何人使用。
Download Dropbox Files
我的猜测是添加另一个 ObservableCollection,它存储被选中的节点和原始树视图节点。因此,当用户启用主复选框时,它会将收藏夹列表加载到 ui,当未选中时,它会重新加载树视图。
// collection of nodes which you see in the image below on the left
public ObservableCollection<INode> DisplayNodes //nodes displayed in UI
public ObservableCollection<INode> FavoriteNodes //nodes marked as favorites
public ObservableCollection<INode> StructureNodes //system node structure
下面的伪函数
public void PopulateUI()
{
DisplayNodes.Clear();
if (showFavorites.isChecked)
{
DisplayNodes = FavoriteNodes;//nodes displayed in UI
}else{
DisplayNodes = StructureNodes;
}
}
我无法从工作中下载您的项目,但我可以就此为您提供一些一般指导。
这可以通过修改您的 INode 实现(FileNode、DirectoryNode 等)以包含 IsFavorite
bool 属性.
在您的视图模型中,添加一个名为 FavoritesEnabled
的 属性。在 属性 的 setter 中,您可以将 RootNodes
可观察对象 collection 替换为 collection 过滤 INode。
private bool favoritesEnabled;
public bool FavoritesEnabled
{
get
{
return this.favoritesEnabled;
}
set
{
this.favoritesEnabled = value;
this.RootNodes = value == true
? new ObservableCollection(this.FilterFavorites)
: new ObservableCollection(this.CreateRootNodes);
}
}
private IEnumerable<INode> FilterFavorites()
{
List<INode> nodes = new List<INode>();
foreach(DirectoryNode directory in this.RootNodes.OfType<DirectoryNode>())
{
nodes.AddRange(this.filterFavorites(nodes, directory.Children.OfType<DirectoryNode>());
nodes.AddRange(this.RootNodes.OfType<FileNode>().Where(item => item.IsFavorite);
}
}
private List<INode> FilterFavorites(List<INode> filteredResults, IEnumerable<DirectoryInfo> directories)
{
// Recursively look up all favorites.
foreach(DirectoryNode directory in directories)
{
filteredResults.AddRange(FilterFavorites(filteredResults, directory));
}
nodes.AddRange(this.RootNodes.OfType<FileNode>().Where(item => item.IsFavorite);
return filteredResults;
}
然后您只需更新树视图的数据模板,以便每个项目的复选框 data-bound 到 INode 实现上的 IsFavorite 属性。
上面的递归代码或多或少是伪造的,因为我无法在不关闭您的项目的情况下对其进行测试。它应该可以帮助您朝着正确的方向开始。使用这种方法,您可以继续只维护一个 collection。您需要将 RootNodes
属性 的创建移出您的构造函数并移至可重用方法中。这样,当您在视图模型中切换收藏夹 属性 时,您的 RootNodes
collection 会生成收藏夹 collection 或 "all" collection.
如果你不能让它工作,我今晚可以从家里拿走你的东西并举一个适当的例子。