c# - 如何在一个 Collection View 源上应用多个过滤器函数,一个接一个(AND 关系)

标签 c# wpf filter observablecollection collectionviewsource

我一直在使用绑定(bind)到 ListView 的 Collection View Source 对象,CVS 是 Observable Collection 对象之上的 View 。

我知道如何使用以下技术应用过滤器:

cvs.Filter += new FilterEventHandler(SomeFilterFunction);

当您只在一个函数中进行过滤时,这很有效。问题是当我想在已经过滤的 CVS 之上过滤时。如果我有另一个函数根据不同的标准过滤 View 中的对象,则对象仅根据第二个过滤器中的标准过滤,第一个过滤器的结果消失。

下面是一些示例代码来解释我的问题:

cvs.Filter += new FilterEventHandler(SomeFilterFunction1);
cvs.Filter += new FilterEventHandler(SomeFilterFunction2);

public void SomeFilterFunction1(object sender, FilterEventArgs e)
{
      SomeObject example = e.Item as SomeObject;
      if(example.Name.Contains("A"))
      {
          e.Accepted = true;
      }
      else
      {
          e.Accepted = false;
      }

}

public void SomeFilterFunction2(object sender, FilterEventArgs e)
{
      SomeObject example = e.Item as SomeObject;
      if(example.Name.Contains("B"))
      {
          e.Accepted = true;
      }
      else
      {
          e.Accepted = false;
      }
}

所以在这个例子中,我只想要过滤器接受字母 A 和 B 的“SomeObjects”。我的问题是,当使用 filterfunction2 调用 cvs+=Filter 时,只接受包含字母 B 的对象名称,而忽略带有字母 A 的对象。因此,包含字母 B 但不包含 A 的对象名称在不应该被接受时被接受.

我目前解决这个问题的方法是创建一个“主”过滤器函数,其中包含每个过滤器函数,我通过每个过滤器运行每个对象,如果对象通过所有过滤器,那么它就会被接受。这确实有效,但我的代码现在变得很疯狂,逻辑也失去了控制。有谁知道如何对 CVS 的最后一个过滤器的结果应用新的过滤器功能?为什么 CVS 不自动执行此操作,而不是通过每个过滤器发送每个对象,或者我没有以正确的方式考虑 CVS?

最佳答案

应用多个过滤器事件处理程序的问题是所有处理程序都被调用并且 CollectionViewSource 没有考虑 e.Accepted 的个别结果。结果将始终是最后一个事件处理程序中的 e.Accepted 的值。

我创建了一个管理器类以允许处理多个 FilterEventHandler 函数并使用 AND 或 OR 逻辑处理它们的结果。因此,要么所有过滤器结果为真,要么至少一个过滤器结果为真。

public class MultipleFilterHandler
{
    private readonly CollectionViewSource collection;

    public MultipleFilterLogic Operation {get; set; }

    public MultipleFilterHandler(CollectionViewSource collection, MultipleFilterLogic operation)
    {
        this.collection = collection;
        this.Operation = operation;
    }

    public MultipleFilterHandler(CollectionViewSource collection) : 
        this( collection, MultipleFilterLogic.Or)
    {
    }

    private event FilterEventHandler _filter;
    public event FilterEventHandler Filter
    { 
        add
        {
            _filter += value;

            collection.Filter -= new FilterEventHandler(CollectionViewFilter);
            collection.Filter += new FilterEventHandler(CollectionViewFilter);
        }
        remove
        {
            _filter -= value;

            collection.Filter -= new FilterEventHandler(CollectionViewFilter);
            collection.Filter += new FilterEventHandler(CollectionViewFilter);
        }
    }

    private void CollectionViewFilter(object sender, FilterEventArgs e)
    {
        if (_filter == null)
            return;

        foreach (FilterEventHandler invocation in _filter.GetInvocationList())
        {
            invocation(sender, e);

            if ((Operation == MultipleFilterLogic.And && !e.Accepted) || (Operation == MultipleFilterLogic.Or && e.Accepted))
                return;
        }
    }
}

public enum MultipleFilterLogic
{
    And,
    Or
}

只需根据需要在 MultipleFilterHandler 的 Filter 属性上添加和删除事件处理程序,它将管理连接 CollectionViewSource。

关于c# - 如何在一个 Collection View 源上应用多个过滤器函数,一个接一个(AND 关系),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12961268/

相关文章:

python-3.x - 如何在python中查找 "filter"对象的长度

wcf - 如何验证、过滤和验证基于 WCF 的 oData 结果?

c# - XNA 4.0 中的自定义光标

c# - 这是否使用字典线程安全?

C# 错误“...的类型初始值设定项抛出异常

c# - DataGridView 标题单元格背景颜色

WPF 拖放列表框

c# - 我的代码是否展示了良好的 WPF 实践?

c# - 如何在 WPF 4.5 中实现 INotifyDataErrorInfo?

c - 重新采样声音样本,我使用什么过滤器?