我有一个ListBox
填充了几个(最多数百个)Phonecall
个对象。我希望能够根据各种标准过滤它们,并且该标准由用户通过表单中的各种复选框决定。理想的情况是用户可以应用过滤器来检查呼叫的时间,呼叫持续的时间以及其他事情。目前,他们一次只能应用一个过滤器。我一开始尝试这样做:
static int MaxDuration = 15;
Predicate<object> timeFilter = (object item) =>
{
Phonecall p = item as Phonecall;
return p.IsBadCall == true; //Decided by method in class definition
};
Predicate<object> durationFilter = (object item) =>
{
Phonecall p = item as Phonecall;
return p.Duration > MaxDuration;
};
...
private void applyFiltBtn_Click(object sender, RoutedEventArgs e)
{
if (timeFilterChkB.IsChecked == true)
CallList.Items.Filter = timeFilter;
if (durFilterChkB.IsChecked == true)
CallList.Items.Filter = durationFilter; //Overrides previous filter
}
在选中两个方框后看到上述内容无效后,我尝试执行以下操作:
CallList.Items.Filter = (o) =>
{
Phonecall pc = o as Phonecall;
if (timeFilterChkB.IsChecked == true && durFilterChkB.IsChecked == false)
return pc.IsBadCall == true;
else if (timeFilterChkB.IsChecked == false && durFilterChkB.IsChecked == true)
return pc.Duration > MaxDuration;
else if (timeFilterChkB.IsChecked == true && durFilterChkB.IsChecked == true)
return pc.IsBadCall == true && pc.Duration > MaxDuration;
else
return true; //No filter is applied
};
它有效,但看起来很难看,只会变成一个很大的,难以阅读的“if-else”树(因为有一些其他属性需要随着时间的推移进行过滤 - 大约10个,我'而不是必须硬编码所有可能的复选框选项。)
简而言之,有没有更好的方法将各种谓词组合到一个过滤器中,或者一次应用多个过滤器,以便只有适合的项目显示在ListBox
?
答案 0 :(得分:1)
这个怎么样:你创建一个类:
class Filter
{
public bool ShouldApply {get;set;}
public Predicate<object> Predicate {get;set;}
}
您的视图模型具有ICollection<Filter> Filters
类型的属性。您将所有谓词添加到此集合中。
复选框与相应的ShouldApply属性绑定数据。
您的过滤代码如下所示:
private void applyFiltBtn_Click(object sender, RoutedEventArgs e)
{
CallList.Items.Filter = (object item) => return filters.All(f=>f(item)); }
答案 1 :(得分:1)
您也可以将两种方法结合起来。对于第一部分,存储谓词列表而不是立即分配:
var predicates = new List<Predicate<object>>();
if (timeFilterChkB.IsChecked == true)
predicates.Add(timeFilter);
if (durFilterChkB.IsChecked == true)
predicates.Add(durationFilter);
对于第二部分,应用所有谓词:
CallList.Items.Filter = o =>
predicates.All(predicate => predicate(o));