【问题标题】:Nested ObservableCollection filtering嵌套的 ObservableCollection 过滤
【发布时间】:2015-04-17 23:28:06
【问题描述】:

我有一个关于过滤 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;
}

这几乎可以按预期工作。

如果某个项目有子项,而过滤器应用,则无法按预期工作。

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

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

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

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

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

周末愉快!

【问题讨论】:

    标签: c# filtering observablecollection


    【解决方案1】:

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

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

    【讨论】:

    • 感谢您的回答。我已经在实现BindableBase,所以不使用ObservableCollection 没有问题。关于逻辑,如果满足谓词,那么我仍然必须在返回项目之前将孩子设置为结果的孩子(即无),否则项目将有其原始孩子。再次感谢您,这回答了我的问题!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 2013-08-26
    • 2015-02-17
    • 2021-11-07
    • 2017-07-27
    • 2014-07-16
    • 2020-07-28
    相关资源
    最近更新 更多