在WPF中将各种过滤器应用于ListBox

时间:2014-06-09 17:36:12

标签: c# wpf lambda listbox delegates

我有一个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

2 个答案:

答案 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));