嵌套的 ObservableCollection 过滤

Nested ObservableCollection filtering

我对 ObservableCollection(及其 children)的过滤有疑问。

我有以下 class:

public class SomeClass
{
    public string Description { get; set; }
    public string CodeFlag { get; set; }
    public double Price { get; set; }
    public List<SomeClass> Children { get; set; }

    public SomeClass()
    {
        this.Children = new List<SomeClass>();
    }

    public SomeClass Search(Func<SomeClass, bool> predicate)
    {
        // the node is a leaf
        if (this.Children == null || this.Children.Count == 0)
        {
            if (predicate(this))
                return this;
            else
                return null;
        }
        else // the node is a branch
        {
            var results = Children.Select(i => i.Search(predicate)).Where(i => i != null).ToList();

            if (results.Any())
            {
                var result = (SomeClass)MemberwiseClone();
                result.Children = results;
                return result;
            }
            /*
             * this is where I'm struggling
            */

            return null;
        }
    }
}

并且在视图模型中具有以下属性:

private ObservableCollection<SomeClass> originalDataSource;
public ObservableCollection<SomeClass> TreeViewDataSource { get; set; }

originalDataSource 在构造函数中设置,而 TreeViewDataSource 是绑定到 TreeView 的集合。

我确信有更好的方法来实现这一点(即只有一个集合)但我现在对此很满意。

最初,要显示集合中的所有项目 - 我只是显示每个项目的描述、代码和价格属性,到目前为止还不错。

现在,视图模型被告知当前过滤器已更改,所以我希望能够像这样进行过滤。

例如,显示“CodeFlag”为“ABC”或“XYZ”的所有项目。

如果过滤器已更改,我将 TreeViewDataSource 设置为:

this.TreeViewDataSource = _getFilteredList(this.originalDataSource);

private ObservableCollection<SomeClass> _getFilteredList(ObservableCollection<SomeClass> originalList)
{
    var filteredItems = new ObservableCollection<SomeClass>();
    SomeClass filterResults = null;

    switch (this.SelectedFilter)
    {
       case SomeEnum.SomeFilterOption:
            filterResults = originalList[0].Search(x => x.CodeFlag.Equals("ABC") || x.CodeFlag.Equals("XYZ"));
       break;

       default:
       break;
    }

    filteredItems.Add(filterResults);

    return filteredItems;
}

这几乎符合预期。

它没有按预期工作的地方是如果一个项目有 children 而过滤器 适用。

在这种情况下,即使项目本身匹配过滤器,因为它的 children 不匹配,返回 null

/*
 * this is where I'm struggling
*/

评论是我认为我需要额外逻辑的地方。

请注意,原始搜索方法归功于@tono-nam

由于今天是周末,我可能与你们中的大多数人处于不同的时区,如果我没有立即回复,请不要生气!

周末愉快!

您不需要 ObservableCollection 来显示您要展示的项目,因为整个集合会立即更改。您可以简单地使用例如一个数组,并让父级 class 实现 INotifyPropertyChanged 以通知整个集合已更改的事实。

要回答关于 return 而不是 null 的问题,请使用与叶子相同的逻辑:return 如果项目与谓词匹配,则 [=12] =] 否则。
您可以通过重新排序条件来简化您的代码:首先获取所有满足谓词的子项,如果有 none (要么因为没有子项,要么因为有子项但它们不匹配 - 不' t matter)然后将集合视为叶子。