2

そのため、プログラムでModelFilterをObjectListViewに追加して、それぞれの2つ(またはそれ以上)の列とフィルターを個別に調べようとしています。現在、ObjectListViewは1つのフィルターしかサポートしていないと思いますが、コード/ドキュメントに何かが欠けている可能性があります。

例として、私の意図したフィルターの1つは、「A」または「T」の値を持つ「アクティブ」列を調べることです。別の列はスーパーバイザー名です。したがって、Supervisor name="Smith"およびActive="A"であるすべてのエントリを検索したいと思います。

TextMatchFilterを使用して、これらのオプションのいずれかに対してフィルターを個別に機能させることはできますが、両方を同時に機能させる方法を理解することはできません。

私が見る小さな問題は、スーパーバイザー名に「A」が含まれている場合、標準のフィルターを使用すると行全体が返されることです。列を表示したくない場合は、プログラムで列のSearchableプロパティをfalseに設定し、リストがフィルター処理されたら再びオンにすることで、これを回避することができました。ただし、[スーパーバイザー]列で[検索可能]をオンにすると、望ましくない結果が得られると感じています。

各フィルターに指定された列のみを使用して、フィルターを複数の列で機能させる方法を知っている人はいますか?

(これを解決するのに役立つサンプルコードはありません。ただし、フィルタリングコードに何があるかを本当に確認したい場合は、喜んで追加します。ただし、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 };

を使用して2つのフィルターを組み合わせて、CompositeAllFilter2つ以上の他のフィルターと一致させることができます。

this.olvEmps.ModelFilter = new CompositeAllFilter(new List<IModelFilter> { filter1, filter2 }); 
于 2012-04-17T23:08:46.687 に答える
1

私はまだあなたの取引を完全には理解していませんが、ここからダウンロードできるLINQKitアセンブリの一部であるPredicateBuilderを使って試してみます。

そのため、複数の列でのフィルタリングが容易になります。ObjectListViewおそらく、ソースコレクションがフィルタリングされたら、コントロールのバインディングをリセットすることを検討する必要があります。

大まかに言って、私は次のことについて行います。

  1. データムをロードします。
  2. データバインディングを介してそれらを表示します。
  3. フィルタのために列をクリックしたら、述語を適用する「Filter」メソッドを呼び出します。
  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 に答える