2009-12-20 32 views
12

Tôi đang sử dụng mẫu thiết kế MVVM, với một ListView được liên kết với một ListCollectionView trên ViewModel. Tôi cũng có một số combobox được sử dụng để lọc ListView. Khi người dùng chọn một mục từ combobox, ListView được lọc cho mục đã chọn. Bất cứ khi nào tôi muốn lọc trên đầu trang của những gì đã được lọc, nó undoes bộ lọc trước của tôi như nó không bao giờ xảy ra. Điều này cũng đúng cho việc loại bỏ một bộ lọc. Việc xóa bộ lọc cho một combobox sẽ xóa tất cả bộ lọc và hiển thị danh sách gốc. Có thể có nhiều bộ lọc riêng biệt trên cùng một ListCollectionView không?WPF Sử dụng nhiều bộ lọc trên cùng một ListCollectionView

Tôi có làm điều gì đó sai hoặc đơn giản là không được hỗ trợ? Bạn có thể tìm thấy ảnh chụp màn hình của ứng dụng của tôi here để xem những gì tôi đang cố gắng hoàn thành. Đây là mã của tôi để lọc ...

/// <summary> 
    /// Filter the list 
    /// </summary> 
    /// <param name="filter">Criteria and Item to filter the list</param> 
    [MediatorMessageSink("FilterList", ParameterType = typeof(FilterItem))] 
    public void FilterList(FilterItem filter) 
    { 
     // Make sure the list can be filtered... 
     if (Products.CanFilter) 
     { 
      // Now filter the list 
      Products.Filter = delegate(object obj) 
      { 
       Product product = obj as Product; 

       // Make sure there is an object 
       if (product != null) 
       { 
        bool isFiltered = false; 
        switch (filter.FilterItemName) 
        { 
         case "Category": 
          isFiltered = (product.Category.IndexOf(filter.Criteria, StringComparison.CurrentCultureIgnoreCase)) != -1 ? true : false; 
          break; 

         case "ClothingType": 
          isFiltered = (product.ClothingType.IndexOf(filter.Criteria, StringComparison.CurrentCultureIgnoreCase)) != -1 ? true : false; 
          break; 

         case "ProductName": 
          isFiltered = (product.ProductName.IndexOf(filter.Criteria, StringComparison.CurrentCultureIgnoreCase)) != -1 ? true : false; 
          break; 

         default: 
          break; 
        } 

        return isFiltered; 
       } 
       else 
        return false; 
      }; 
     } 
    } 

Trả lời

25

Mỗi lần bạn đặt thuộc tính Bộ lọc bạn đặt lại bộ lọc trước đó. Đây là sự thật. Bây giờ làm thế nào bạn có thể có nhiều bộ lọc?

Như bạn đã biết, có hai cách để lọc: CollectionViewCollectionViewSource. Trong trường hợp đầu tiên với CollectionView, chúng tôi lọc với đại biểu và để thực hiện nhiều bộ lọc, tôi sẽ tạo một lớp để tổng hợp các bộ lọc tùy chỉnh và sau đó gọi từng bộ lọc cho từng mục bộ lọc. Giống như trong đoạn mã sau:

public class GroupFilter 
    { 
    private List<Predicate<object>> _filters; 

    public Predicate<object> Filter {get; private set;} 

    public GroupFilter() 
    { 
     _filters = new List<Predicate<object>>(); 
     Filter = InternalFilter; 
    } 

    private bool InternalFilter(object o) 
    { 
     foreach(var filter in _filters) 
     { 
     if (!filter(o)) 
     { 
      return false; 
     } 
     } 

     return true; 
    } 

    public void AddFilter(Predicate<object> filter) 
    { 
     _filters.Add(filter); 
    } 

    public void RemoveFilter(Predicate<object> filter) 
    { 
     if (_filters.Contains(filter)) 
     { 
     _filters.Remove(filter); 
     } 
    }  
    } 

    // Somewhere later: 
    GroupFilter gf = new GroupFilter(); 
    gf.AddFilter(filter1); 
    listCollectionView.Filter = gf.Filter; 

Để làm mới chế độ xem được lọc, bạn có thể gọi đến phương thức ListCollectionView.Refresh().

Và trong trường hợp thứ hai với CollectionViewSource bạn sử dụng Filter sự kiện để lọc bộ sưu tập. Bạn có thể tạo nhiều trình xử lý sự kiện để lọc theo các tiêu chí khác nhau. Để đọc thêm về cách tiếp cận này, hãy kiểm tra bài viết tuyệt vời này của Bea Stollnitz: How do I apply more than one filter?

Hy vọng điều này sẽ hữu ích.

Chúc mừng, Anvaka.

+0

Tôi biết đã gần một thập kỷ sau, nhưng liên kết đã chết. – KSwift87

8

Mỗi lần người dùng lọc, mã của bạn là thay thế số Filter ủy quyền trong chế độ xem bộ sưu tập của bạn bằng chế độ xem mới, mới. Hơn nữa, cái mới chỉ kiểm tra các tiêu chí cụ thể mà người dùng vừa chọn với một số ComboBox.

Điều bạn muốn là một trình xử lý bộ lọc duy nhất kiểm tra tất cả các tiêu chí. Một cái gì đó như:

public MyViewModel() 
{ 
    products = new ObservableCollection<Product>(); 
    productsView = new ListCollectionView(products); 
    productsView.Filter += FilterProduct; 
} 

public Item SelectedItem 
{ 
    //get,set omitted. set needs to invalidate filter with refresh call 
} 

public Type SelectedType 
{ 
    //get,set omitted. set needs to invalidate filter with refresh call 
} 

public Category SelectedCategory 
{ 
    //get,set omitted. set needs to invalidate filter with refresh call 
} 

public ICollection<Product> FilteredProducts 
{ 
    get { return productsView; } 
} 

private bool FilterProduct(object o) 
{ 
    var product = o as Product; 

    if (product == null) 
    { 
     return false; 
    } 

    if (SelectedItem != null) 
    { 
     // filter according to selected item 
    } 

    if (SelectedType != null) 
    { 
     // filter according to selected type 
    } 

    if (SelectedCategory != null) 
    { 
     // filter according to selected category 
    } 

    return true; 
} 

Chế độ xem của bạn bây giờ có thể chỉ gắn với thuộc tính thích hợp và lọc sẽ hoạt động.

Các vấn đề liên quan