2009-12-20 30 views
12

मैं एमवीवीएम डिज़ाइन पैटर्न का उपयोग कर रहा हूं, एक सूची दृश्य के साथ ViewMiewel पर ListCollectionView से जुड़ा हुआ है। मेरे पास कई comboboxes भी हैं जिनका उपयोग ListView को फ़िल्टर करने के लिए किया जाता है। जब उपयोगकर्ता combobox से कोई आइटम चुनता है, तो सूची दृश्य को चयनित आइटम के लिए फ़िल्टर किया जाता है। जब भी मैं पहले से फ़िल्टर किए गए शीर्ष पर फ़िल्टर करना चाहता हूं, तो यह मेरे पिछले फ़िल्टर को पूर्ववत करता है जैसे कि यह कभी नहीं हुआ। फ़िल्टर को हटाने के लिए भी यही सच है। एक combobox के लिए एक फ़िल्टर को हटाने सभी फिल्टर हटा देता है और मूल सूची प्रदर्शित करता है। क्या एक ही ListCollectionView पर एकाधिक, अलग-अलग फ़िल्टर होना संभव है?WPF एक ही सूची पर एकाधिक फ़िल्टर का उपयोग कर चयन करें

क्या मैं कुछ गलत कर रहा हूं, या यह बस समर्थित नहीं है? मैं यह देखने के लिए कि मैं क्या पूरा करने की कोशिश कर रहा हूं, आप मेरे आवेदन here का स्क्रीन कैप्चर पा सकते हैं। फ़िल्टरिंग के लिए मेरा कोड यहां है ...

/// <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; 
      }; 
     } 
    } 

उत्तर

25

हर बार जब आप फ़िल्टर प्रॉपर्टी सेट करते हैं तो आप पिछले फ़िल्टर को रीसेट करते हैं। यह सच है। अब आपके पास एकाधिक फ़िल्टर कैसे हो सकते हैं?

जैसा कि आप जानते हैं, फ़िल्टरिंग करने के दो तरीके हैं: CollectionView और CollectionViewSourceCollectionView के साथ पहले मामले में हम प्रतिनिधि के साथ फ़िल्टर करते हैं, और कई फ़िल्टर करने के लिए मैं कस्टम फ़िल्टर को एकत्र करने के लिए एक कक्षा तैयार करता हूं और फिर प्रत्येक फ़िल्टर आइटम के लिए उन्हें एक-एक करके कॉल करता हूं। निम्नलिखित कोड में की तरह:

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; 

फ़िल्टर किया गया दृश्य आप ListCollectionView.Refresh() विधि करने के लिए एक कॉल कर सकते ताज़ा करने के लिए।

और दूसरे मामले में CollectionViewSource के साथ आप संग्रह फ़िल्टर करने के लिए Filter ईवेंट का उपयोग करते हैं। आप विभिन्न मानदंडों द्वारा फ़िल्टर करने के लिए एकाधिक ईवेंट हैंडलर बना सकते हैं। इस दृष्टिकोण के बारे में अधिक पढ़ने के लिए बीए स्टॉलनिट्ज़ द्वारा इस अद्भुत लेख की जांच करें: How do I apply more than one filter?

आशा है कि इससे मदद मिलती है।

चीयर्स, अंवाका।

+0

मुझे पता है कि यह लगभग एक दशक बाद है, लेकिन लिंक मर चुका है। – KSwift87

8

हर बार जब उपयोगकर्ता फ़िल्टर करता है, तो आपका कोड Filter को अपने संग्रह दृश्य में नए, ताजा एक के साथ प्रतिस्थापित करता है। इसके अलावा, नया केवल उस विशेष मानदंड की जांच करता है जिसे उपयोगकर्ता ने ComboBox के साथ चुना है।

आप जो चाहते हैं वह एक फ़िल्टर हैंडलर है जो सभी मानदंडों की जांच करता है। कुछ ऐसा:

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

आपका विचार अब उचित गुणों से जुड़ सकता है और फ़िल्टरिंग केवल काम करेगी।