2010-01-29 2 views
13

검색 확장이 포함 된 사용자 지정 WPF 컨트롤을 작성했습니다. 이름을 MyControl으로 지정합시다. 컨트롤은 ItemsControl 클래스의 자손입니다.WPF CollectionViewSource 다중 뷰?

는 그래서 이런 식으로 데이터 소스를 공급 : 는

제어 자체는 소스 컬렉션의보기를 필터링

protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue) 
{ 
    if (newValue != null) 
    { 
     ICollectionView view = CollectionViewSource.GetDefaultView(newValue); 
     view.Filter += this.FilterPredicate; 
    } 

    if (oldValue != null) 
    { 
     ICollectionView view = CollectionViewSource.GetDefaultView(oldValue); 
     view.Filter -= this.FilterPredicate; 
    } 

    base.OnItemsSourceChanged(oldValue, newValue); 
} 

사용 (따라서 내측리스트 박스를 표시).

이제 우리는 동일한 DynamicSource를 사용하여 XAML에 정의 된 MyControls가 10 개 있다고 가정합니다. 그 중 하나가 소스 컬렉션에 필터를 적용하면 다른 모든 인스턴스에도 영향을 미칩니다.

이 동작을 피하기 위해 컨트롤을 어떻게 변경 하시겠습니까?

답변

26

이와 같은 상황에서 일반적으로 컬렉션의 다르게 필터링 된 사용에 대해 별도의 ICollectionView 인스턴스를 만들려고합니다. ItemsSource가 다른 컬렉션 유형에 바인딩 된 경우 변경해야하는 CollectionView 유형이 가능하기 때문에 ICollectionView의 특정 구현을 사용하는 것은 좋지 않습니다.

ICollectionView filteredView = new CollectionViewSource { Source=newValue }.View; 

을 사용하면 올바른 유형의 ICollectionView가 자동으로 제공됩니다.

아쉽게도이 경우 사용자 지정 컨트롤의 ItemsPresenter에 다른 Collection을 적용하기가 매우 어렵습니다. 왜냐하면 모든 마법은 기본 ItemsControl 클래스에 의해 수행되고 ItemsSource에 의존하기 때문입니다/그것이 관리하는 아이템 속성들. 이 문제는 ItemsControl의 기본 템플릿과 비슷한 것을 사용할 때 발생합니다.

ControlTemplate 안에 실제로 별도의 ListBox 컨트롤 (그리고 필요한 경우 모든 ItemsSource 속성 TemplateBinding)을 사용하고 있다면 새로운 ICollectionView DP를 간단히 추가 할 수 있어야합니다 (읽기 전용) 컨트롤에서 컬렉션의 필터링 된 버전을 보유하고 ListBox의 ItemsSource 템플릿을 새 속성에 바인딩합니다.

+0

대단히 좋습니다. 정말 고맙습니다. 대단히 감사합니다! 그냥 noobie 질문입니다 - RegisterReadOnly()는 '읽기 전용'이라고 말하면 무슨 뜻입니까? –

+0

ItemsSourceView에서 ItemsSourceView = new CollectionViewSource {Source = newValue} .View를 설정했기 때문에 ItemsSourceView가 DP 인 경우 Setter를 단순히 삭제할 수 없기 때문에 ItemsSourceChanged에서 묻습니다. –

+2

예. 그것은 단지 초기화를 변경하는 것 이상의 것입니다 : private static 읽기 전용 DependencyPropertyKey MyDPPropertyKey = DependencyProperty.RegisterReadOnly (...); public static readonly DependencyProperty MyDPProperty = MyDPPropertyKey입니다.DependencyProperty; 공용 개체 MyDP { \t get {return (object) GetValue (MyDPProperty); } \t 개인 집합 {SetValue (MyDPPropertyKey, value); } } –

4

CollectionViewSource.GetDefaultView(object)은 주어진 소스에 대해 항상 인스턴스를 반환하며 이는 해당 소스를 표시 할 때 ItemsControl 확장명이 사용하는 것입니다.

컬렉션을 독립적으로 필터링하고 각 컨트롤의 ItemsSource 속성을 해당 특정보기에 명시 적으로 바인딩 할 수 있도록 각 컨트롤에서 사용할 ICollectionView이라는 새 인스턴스를 만들어이 문제를 해결할 수 있습니다. ICollectionView 유형은 시나리오에 따라 다르지만 일반적으로 ListCollectionView이 적합합니다.