所以,我试图以编程方式将ModelFilter添加到我的ObjectListView中,它将分别查看两个(或更多)列和过滤器。目前,我认为ObjectListView只支持一个过滤器,但我可能在代码/文档中遗漏了一些东西。
例如,我的一个预期过滤器是查看“Active”列,其值为“A”或“T”。另一栏是主管姓名。所以,我想找到Supervisor name =“Smith”和Active =“A”的所有条目。
我可以使用TextMatchFilter分别使用过滤器来处理这些选项中的任何一个,但是无法弄清楚如何让它们同时工作。
我看到的一个小问题是,如果超级用户名包含“A”,那么使用标准过滤器将返回整行。我已经能够通过以编程方式将列的Searchable属性设置为false来解决这个问题,如果我不想查看它们,然后在列表被过滤后再将它们重新打开。但是,我有一种感觉,如果我将Searchable打开为Supervisor专栏,我会得到不想要的结果。
有没有人知道让过滤器在多个列上工作的方法,只使用每个过滤器的指示列?
(我没有示例代码可以帮助解决这个问题。但是,如果你真的想看看我的滤波代码是什么,我会乐意添加它;但是它在VB中。)
当前代码 - 查看用户选择的值(searchMeth)并启用对该列的搜索。然后它搜索txtSearch框中输入的内容。但是,除此之外,我还想为Supervisor添加一个额外的过滤器。 (参见AndAlso评论
olvEmps.UseFiltering = True
OlvColumn1.Searchable = False
OlvColumn2.Searchable = False
OlvColumn4.Searchable = False
OlvColumn3.Searchable = False
OlvColumn5.Searchable = False
Select Case searchMeth
Case "Name"
OlvColumn1.Searchable = True
Case "Employee Number"
OlvColumn2.Searchable = True
Case "Department"
OlvColumn3.Searchable = True
End Select
olvEmps.OwnerDraw = True
Dim tFilter As BrightIdeasSoftware.TextMatchFilter = BrightIdeasSoftware.TextMatchFilter.Contains(olvEmps, txtSearch.Text)
'andalso olvColumn5 = supeName?
olvEmps.ModelFilter = tFilter
olvEmps.DefaultRenderer = New BrightIdeasSoftware.HighlightTextRenderer(tFilter)
OlvColumn1.Searchable = True
OlvColumn2.Searchable = True
OlvColumn3.Searchable = True
OlvColumn4.Searchable = True
OlvColumn5.Searchable = True
答案 0 :(得分:7)
我确信PredicateBuilder解决方案可行,但ObjectListView
已经提供了一个更简单的解决方案。
TextMatchFilter
可以限制为通过Columns
属性搜索的列。将其设置为您要考虑的列数组。
TextMatchFilter filter1 = TextMatchFilter.Contains(olvEmps, txtSearch.Text)
filter1.Columns = new [] { this.olvColumn1, this.olvColumn2 };
您可以使用CompositeAllFilter
组合两个过滤器,以匹配两个或更多其他过滤器。
this.olvEmps.ModelFilter = new CompositeAllFilter(new List<IModelFilter> { filter1, filter2 });
答案 1 :(得分:1)
虽然我还没有完全理解你的交易,但我会用PredicateBuilder给你一个镜头,它是LINQKit程序集的一部分,你可以下载here。
因此,对多列进行过滤将变得容易。也许您应该考虑在过滤源集合后重置ObjectListView
控件的绑定。
总的来说,我会做以下几点:
请参阅前面提供的链接中的PredicateBuilder文档。此处说明了构建动态过滤器的另一个示例:对于我实施的搜索引擎,“How would this query translate into a dynamic Linq expression?”。
就我而言,过滤器直接应用于数据库结果。除此之外,它甚至可以在内存数据的情况下使用,因为它是基于Linq的。
我确信当您发布代码示例以过滤信息时,我将能够提供进一步的帮助。
编辑#1
在我阅读了提供的代码示例之后,我认为这就是诀窍。至于Searchable属性,我对这种方法并不熟悉,所以也许我会错过你的代码中的重要内容,如果是这样的话,请随意指出我可能错过的内容。 =)
请注意,我假设您的所有数据都是字符串,因为我正在验证您的数据是空还是空格。此外,我看到它的方式,过滤结果集是为了只显示符合特定标准的记录。您不希望看到不符合标准的内容。它与SQL中的WHERE子句相同。
public class FilterCriterion {
public bool HasEmployeeName { get { return !string.IsNullOrWhiteSpace(EmployeeName); } }
public bool HasEmployeeNumber { get { return !string.IsNullOrWhiteSpace(EmployeeNumber); } }
public bool HasDepartment { get { return !string.IsNullOrWhiteSpace(Department); } }
public string EmployeeName { get; set; }
public string EmployeeNumber { get; set; }
public string Department { get; set; }
}
FilterCriterion类应用于对数据源,集合或任何内容应用您想要的任何过滤器。
var employees = LoadEmployeesFromUnderlyingDataStore();
var criterion = new FilterCriterion();
switch(searchMeth) {
case "Name": filter.EmployeeName = "the name to filter by"; break;
case "EmployeeNumber": filter.EmployeeNumber = "the number to filter by"; break;
case "Department": filter.Department = "the department to filter by"; break;
}
var filter = PredicateBuilder.True<Employee>(); // assuming you have an employee class.
if (criterion.HasEmployeeName)
filter.And(e => e.Name.ContainsLike(criterion.EmployeeName));
if (criterion.HasEmployeeNumber)
filter.And(e => e.EmployeeNumber.ContainsLike(criterion.EmployeeNumber));
if (criterion.HasDepartment)
filter.And(e => e.Department.ContainsLike(criterion.Department));
var filteredEmployees = employees.Where(filter);
// Supply your ObjectListView the way you're used to and this shall function.
除此之外,您还可以,如果必须处理此类字符串变量,请将ContainsLike
扩展方法写入字符串类。
namespace System {
public static class StringExtensions {
public static bool ContainsLike(this string input, string value) {
if (string.IsNullOrWhiteSpace(input) || string.IsNullOrWhiteSpace(value)) return false;
input = input.ToLower().RemoveDiacritics();
value = value.ToLower().RemoveDiacritics();
if (string.IsNullOrWhiteSpace(input) || string.IsNullOrWhiteSpace(value)) return false;
return input.Contains(value);
}
public static string RemoveDiacritics(this string input) {
return input == null ? null :
Encoding.ASCII.GetString(Encoding.GetEncoding(1251).GetBytes(input));
}
}
}
我希望这会有所帮助,否则告诉我我从你的问题中误解了什么,我们会一起尝试解决这个问题。
如果你需要这个代码的VB版本,我会尝试翻译我最好的VB知识。
此代码按原样提供,尚未经过测试,但两种字符串扩展方法除外。