嵌套的ObservableCollection过滤

时间:2015-04-17 14:23:06

标签: c# filtering observablecollection

我有一个关于过滤ObservableCollection(及其子项)的问题。

我有以下课程:

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

这几乎按预期工作。

如果项目没有按预期工作,那么过滤器 NOT 应用的项目是否为子项。

在这种情况下,即使项目本身与过滤器匹配,如其子项不匹配,也会返回 null

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

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

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

因为这是周末而且我和你们绝大多数人的时区不同,如果我不立即回应,请不要被冒犯!

周末愉快!

1 个答案:

答案 0 :(得分:1)

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

要回答关于返回什么而不是null的问题,请使用与叶子相同的逻辑:如果项目与谓词匹配则返回该项目,否则返回null。 您可以通过重新排序条件来简化代码:首先获取满足谓词的所有子项,如果没有,(或者因为没有子项,或者因为有子项但它们不匹配 - 无关紧要)将收藏品当作一片叶子。