2

因此,我试图以编程方式将 ModelFilter 添加到我的 ObjectListView 中,它将分别查看两个(或更多)列和过滤器。目前,我认为 ObjectListView 只支持一个过滤器,但我可能在代码/文档中遗漏了一些东西。

例如,我的预期过滤器之一是查看“Active”列,其值为“A”或“T”。另一列是主管姓名。因此,我想找到主管名称 =“Smith”且 Active =“A”的所有条目。

我可以使用 TextMatchFilter 让过滤器分别为这些选项中的任何一个工作,但无法弄清楚如何让这两个选项同时工作。

我看到的小问题是,如果主管名称包含“A”,那么使用标准过滤器将返回整行。如果我不想查看它们,我可以通过以编程方式将列的 Searchable 属性设置为 false 来解决这个问题,然后在过滤列表后重新打开它们。但是,我有一种感觉,如果我为 Supervisor 列打开 Searchable,我会得到不需要的结果。

有谁知道让过滤器在多个列上工作的方法,只为每个过滤器使用指定的列?

(我没有示例代码可以帮助解决这个问题。但是,如果您真的想看看我的过滤代码有什么,我很乐意添加它;但是它在 VB 中)。

当前代码 - 这会查看用户选择的值 (searchMeth) 并启用在该列上的搜索。然后它会搜索在 txtSearch 框中输入的内容。但是,除此之外,我想为主管添加一个额外的过滤器。(参见 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
4

2 回答 2

8

我确信 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 }); 
于 2012-04-17T23:08:46.687 回答
1

虽然我还没有完全理解你的交易,但我会用PredicateBuilder来试一试,它是 LINQKit 程序集的一部分,你可以在这里下载。

因此,对多列进行过滤会变得容易。ObjectListView一旦您的源集合被过滤,您也许应该考虑重置您的控件的绑定。

总的来说,我会做以下事情:

  1. 加载您的数据;
  2. 通过数据绑定展示它们;
  3. 单击列进行过滤后,调用您的“过滤器”方法,该方法将应用您的谓词;
  4. 使用新过滤的集合重新绑定您的控件。

请参阅前面提供的链接中的 PredicateBuilder 文档。构建动态过滤器的另一个示例如下所示:“如何将这个查询转换为动态 Linq 表达式? ”对于我实现的搜索引擎。

就我而言,过滤器直接应用于数据库结果。此外,它甚至可以用于内存数据,因为它是基于 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 知识。

此代码按原样提供,未经测试,字符串扩展方法除外。

于 2012-03-22T03:23:41.953 回答