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.

如果你不能让它工作,我今晚可以从家里拿走你的东西并举一个适当的例子。