我一直在使用绑定(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/