3

私はリストビューにバインドされたコレクションビューソースオブジェクトを操作してきましたが、CVSはオブジェクトの監視可能なコレクションの上にあるビューです。

次の手法を使用してフィルターを適用する方法を知っています。

cvs.Filter += new FilterEventHandler(SomeFilterFunction);

これは、1つの関数でのみフィルタリングする場合に正常に機能します。問題は、すでにフィルタリングされたCVSの上でフィルタリングしたい場合です。異なる基準に基づいてビュー内のオブジェクトをフィルター処理する別の関数がある場合、オブジェクトは2番目のフィルターの基準でのみフィルター処理され、最初のフィルターの結果は表示されなくなります。

これが私の問題を説明するためのいくつかのサンプルコードです:

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を呼び出すと、文字Aのオブジェクトを無視して、文字Bを含むオブジェクト名のみが受け入れられることです。したがって、文字Bを含むオブジェクト名は受け入れられますが、Aは受け入れられません。 。

この問題に対する私の現在の解決策は、すべてのフィルター関数を内部に持つ「マスター」フィルター関数を作成することであり、すべてのオブジェクトをすべてのフィルターに通し、オブジェクトがすべてのフィルターを通過すると受け入れられます。これは機能しますが、私のコードは今狂っていて、ロジックは制御不能になっています。CVSの最後のフィルターの結果に新しいフィルター関数を適用する方法を知っている人はいますか?すべてのオブジェクトをすべてのフィルターに送信する代わりに、CVSがこれを自動的に実行しないのはなぜですか、またはCVSについて正しい方法で考えていないのですか?

4

2 に答える 2

1

問題は、複数のフィルター イベント ハンドラーを適用することです。すべてのハンドラーが呼び出され、個々の結果が考慮されCollectionViewSourceないことです。e.Accepted結果は、常にe.Accepted最後のイベント ハンドラーの値になります。

複数の関数を処理できるマネージャー クラスを作成し、FilterEventHandlerその結果を AND または OR ロジックで処理します。したがって、すべてのフィルタ結果が true になるか、少なくとも 1 つのフィルタ結果が true になります。

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 の接続が管理されます。

于 2013-04-12T18:55:03.570 に答える
1

これを行うことができます:

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

public void SomeFilterFunction1(object sender, FilterEventArgs e)
{
      SomeObject example = e.Item as SomeObject;
      e.Accepted &= example.Name.Contains("A");
      //if you prefer OR logic use this one:          
      //e.Accepted |= example.Name.Contains("A");

}

public void SomeFilterFunction2(object sender, FilterEventArgs e)
{
      SomeObject example = e.Item as SomeObject;
      e.Accepted &= example.Name.Contains("B");
      //if you prefer OR logic use this one:
      //e.Accepted |= example.Name.Contains("B");
}

これにより、Accepted プロパティの現在の値と AND (または |= 演算子を使用する場合は OR) が行われ、フィルターが連携して機能します。

編集:これは.NET 4.5で作成されました

于 2014-12-13T11:37:11.380 に答える