2012-10-18 3 views
2

나는 콜렉션 뷰를 사용하여 작업하고있다. listview에 바인딩 된 소스 객체이며 CVS는 Observable Collection 개체. 하나의 콜렉션 뷰 소스에 여러 필터 함수를 차례로 적용하는 방법 (AND 관계)

나는 다음과 같은 기술을 사용하여 필터를 적용하는 방법을 알고 : 당신이 하나 개의 기능에 필터링 할 때 잘 작동

cvs.Filter += new FilterEventHandler(SomeFilterFunction); 

. 문제는 이미 필터링 된 CVS를 필터링하려고 할 때입니다. 다른 기준에 따라 뷰의 개체를 필터링하는 다른 함수가있는 경우 개체는 두 번째 필터의 조건에서만 필터링되고 첫 번째 필터의 결과는 사라집니다.

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"를 원하는

: 여기

내 문제를 설명하는 몇 가지 예제 코드입니다. 내 문제는 그 때 전화 Cvs + = filterfunction2와 함께 필터, 문자 B를 포함하는 개체 이름 만 허용됩니다, 문자 A와 함께 개체를 무시합니다. 그래서 문자가 포함되어 있지만 A가 아니라면 그들이 받아 들여지지 않을 때 허용됩니다. .

이 문제에 대한 나의 현재의 해결책은 모든 필터 기능을 가진 "마스터"필터 기능을 만들고 모든 필터를 통해 모든 개체를 실행하고 개체가 모든 필터를 통과하면 받아들입니다. . 이것은 작동하지만 내 코드가 지금 미쳐지고 논리가 제어 불능 상태가되고 있습니다. 누구든지 CVS에 대한 마지막 필터의 결과에 새로운 필터 함수를 적용하는 방법을 알고 있습니까? 왜 CVS는 모든 필터를 통해 모든 객체를 보내는 대신 자동으로이 작업을 수행하지 않습니까? 아니면 올바른 방법으로 CVS를 생각하지 않습니까?

답변

1

문제가 여러 필터 이벤트 처리기를 적용하면 모든 처리기가 호출되고 CollectionViewSourcee.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의 필터 속성에, 그리고 그것은 CollectionViewSource를 배선을 관리합니다.

+0

내 상황이 (가 확인 된 바와 같이 GUI에서 체크 박스에 대해) 내가 런타임에 여러 필터 이벤트 처리기를 추가 한 것이 었습니다. 나는 예측할 수없는 결과를 얻고 있었다. 여기에 결과를 편집하고 편집 해 보겠습니다. –

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"); 
} 

는 이것이 할 것입니다 것은 DO와 AND (= 연산자 또는 OR 당신은을 사용하는 경우)입니다 함께.

편집 : 이것은 .NET 4.5에서 만들어진

관련 문제