2013-07-10 58 views
2

tldr:CollectionViewSource.Filter被另一個控件覆蓋。我如何擁有兩層過濾器,以便控件只能看到預過濾的集合?CollectionViewSources是否可嵌套?

我有一個第三方gridcontrol,我通過ICollectionView綁定到我的viewmodel中的集合。

private CollectionViewSource _filteredCollection; 

public ItemListViewModel (List<ItemViewModel> items) 
{ 
    _items = items; 
    _filteredCollection = new CollectionViewSource {Source = _items}; 
} 

public ICollectionView AllInstructions 
{ 
    get { return _filteredCollection.View; } 
} 

這工作正常,並允許gridcontrol做自己的過濾,分組和排序。 現在我想網格的一個前申請我自己的過濾器(即一個按鈕,僅顯示今天的項目)

public ItemListViewModel (List<ItemViewModel> items) 
{ 
    ... 
    _filteredCollection.Filter += new FilterEventHandler(FilterByDate); 
} 

private void FilterByDate(object sender, FilterEventArgs e) 
{ 
    var item = e.Item as ItemViewModel; 

    if (item == null) 
    { 
     e.Accepted = false; 
    } 
    else 
    { 
     e.Accepted = item.CreatedDate >= _selectedDate; 
    } 
} 

我的新過濾器工作正常。 問題是,網格控件不能很好地播放它,而只是用自己的代碼覆蓋任何過濾器。

我的想法是在_filteredCollection CVS上執行我的過濾,然後在其周圍創建另一個CollectionViewSource或CollectionView,並將其傳遞給gridcontrol。

如果我將_filteredCollection包裝在ICollectionView中,兩層過濾工作正常,但我無法排序或分組,因爲ICollectionView的默認構造函數將CanSort和CanGroup設置爲false。

我無法弄清楚如何將_filteredCollection提供給第二個CollectionViewSource的構造函數。這是可能的還是我從錯誤的角度來處理這個問題?

回答

2

您可以通過下面的代碼從ListCollectionView派生,如創建與預定義過濾器自己的收藏視圖用任何控件都可以測試,但我認爲它應該可以工作。

2

如果我理解它是正確的,你想要在你的列表中應用幾個過濾器,不是嗎?

如何將Filter過濾到管理多個謂詞的主FilterHandler。爲了使它更加靈活,您可以將這些謂詞添加到您的主FilterHandler將卸載的列表或堆棧中。由於CollectionViewSources的刷新過程,我相信任何新的過濾器將在下一個Refresh()中被考慮。

class FilteredListCollectionView : ListCollectionView 
{ 
    // internal filter 
    private Predicate<object> preFilter; 

    // public filter 
    private Predicate<object> filter; 

    public FilteredListCollectionView(IList list) 
     : base(list) 
    { 
    } 

    private Predicate<object> GetCombinedFilter() 
    { 
     if (this.preFilter != null) 
      return this.filter != null ? x => this.preFilter(x) && this.filter(x) : this.preFilter; 
     else 
      return this.filter; 
    } 

    public Predicate<object> PreFilter 
    { 
     get { return this.preFilter; } 
     set 
     { 
      this.preFilter = value; 
      base.Filter = this.GetCombinedFilter(); 
     } 
    } 

    public override Predicate<object> Filter 
    { 
     get { return base.Filter; } 
     set 
     { 
      this.filter = value; 
      base.Filter = this.GetCombinedFilter(); 
     } 
    } 
} 

現在你可以使用它像這樣:

private FilteredListCollectionView _filteredCollection; 

public ItemListViewModel(List<ItemViewModel> items) 
{ 
    _items = items; 
    _filteredCollection = new FilteredListCollectionView(_items); 
    _filteredCollection.PreFilter = FilterByDate; 
} 

public ICollectionView AllInstructions 
{ 
    get { return _filteredCollection; } 
} 

private bool FilterByDate(object obj) 
{ 
    var item = obj as ItemViewModel; 

    if (item == null) 
    { 
     return false; 
    } 
    else 
    { 
     return item.CreatedDate >= _selectedDate; 
    } 
} 

我的避風港」