嵌套的 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)然后将集合视为叶子。
我对 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)然后将集合视为叶子。