2012-10-31 29 views
1

我有一個ListView說我有ObservableCollection如何從各種文本框(多個標準)篩選ObservableCollection?

我過濾來自於TextBox

這裏輸入的文本列表填充的代碼的部分我使用:

private void Filter_TextChanged(object sender, TextChangedEventArgs e) 
    { 
      view = CollectionViewSource.GetDefaultView(Elementos_Lista.ItemsSource); 
      view.Filter = null; 
      view.Filter = new Predicate<object>(FilterList); 
    } 

這工作正常,如果我想通過一個標準篩選列表,但每當我想要混合多個文本框進行篩選時,它總是基於ItemsSource進行篩選,而不是當前結果集,這意味着沒有標準積累。

這是我的FilterList方法。

ItemDetail item = obj as ItemDetail; 
if (item == null) return false; 
string textFilter = txtFilter.Text; 
if (textFilter.Trim().Length == 0) return true; //this returns the unfiltered results. 
if ((item.problema.ToLower().Contains(textFilter.ToLower()))) return true; 
return false; 

有一種方法來篩選由多個標準的ObservableCollection(圖)時,並不總是在相同的時間提供?

我試圖改變FilterList方法來評估各種文本框,但我將不得不作出IF語句來檢查匹配條件的所有可能性。

(filter1=value , filter2=value) OR 
(filter1=value , filter2=empty) OR 
(filter1=empty , filter2=value) 

而且由於我打算至少過濾5個不同的控件,這根本就不會有趣。

例子:

List: 
Maria, Age:26 
Jesus, Age:15 
Angela, Age:15 

第一過濾

Filters: 
Name: //Empty 
Age: 15 

Result: 
Jesus, Age:15 
Angela, Age:15 

第二過濾器:

Filters: 
Name: Jesus 
Age: 15 

Result: 
Jesus, Age:15 

我想要做的就是將過濾器應用於已過濾收集,並不是原來的,這種方法會覆蓋下一個應用的過濾器。

回答

1

OK,讓我們來看看,我有類似的東西趴在這裏...

[ContractClass(typeof(CollectionViewFilterContracts<>))] 
public interface ICollectionViewFilter<in T> where T : class 
{ 
    bool FilterObject(T obj); 
} 

合同是選修課(CodeContracts

[ContractClassFor(typeof(ICollectionViewFilter<>))] 
    public abstract class CollectionViewFilterContracts<T> : ICollectionViewFilter<T> where T : class 
    { 
     public bool FilterObject(T obj) 
     { 
      Contract.Requires<ArgumentNullException>(obj != null, "Filtered object can't be null"); 

      return default(bool); 
     } 
    } 

然後基實現的,你只用字符串進行比較,據我所知,所以這裏是字符串版本:

public abstract class CollectionFilterBase<T> : ICollectionViewFilter<T> where T : class 
    { 

     private readonly Dictionary<string, string> filters = new Dictionary<string, string>(10); 
     private readonly PropertyInfo[] properties; 

     protected CollectionFilterBase() 
     { 
      properties = typeof(T).GetProperties(); 
     }   

     protected void AddFilter(string memberName, string value) 
     { 
      if (string.IsNullOrEmpty(value)) 
      { 
       filters.Remove(memberName); 
       return; 
      } 

      filters[memberName] = value; 
     } 

     public virtual bool FilterObject(T objectToFilter) 
     { 
      foreach (var filterValue in filters) 
      { 
       var property = properties.SingleOrDefault(x => x.Name == filterValue.Key); 
       if(property == null) 
        return false; 

       var propertyValue = property.GetValue(objectToFilter, null); 
       var stringValue = propertyValue == null ? null : propertyValue.ToString(); // or use string.Empty instead of null, depends what you're going to do with it. 
       // Now you have the property value and you have your 'filter' value in filterValue.Value, do the check, return false if it's not what you're looking for. 
       //The filter will run through all selected (non-empty) filters and if all of them check out, it will return true. 
      } 

      return true; 
     } 
    } 

現在一些有意義的實現,讓我們說這是你的班,爲了簡單:

public class Person 
{ 
    public string Name {get;set;} 
    public int Age {get;set;} 
} 

濾波器實現 - 在同一時間 - 包含視圖背後的視圖模型所有的「過濾」的控制,所以你相應地將文本框值綁定到屬性。

public class PersonFilter : CollectionFilterBase<Person> 
{ 
    private string name; 
    public string Name 
    { 
     get 
     { 
      return name; 
     } 

     set 
     { 
      name = value; 
      //NotifyPropertyChanged somehow, I'm using Caliburn.Micro most of the times, so: 
      NotifyOfPropertyChange(() => Name); 
      AddFilter("Name", Name);    
     } 
    } 
    private int age; 
    public int Age 
    { 
     get 
     { 
      return age; 
     } 
     set 
     { 
      age = value; 
      //Same as above, notify 
      AddFilter("Age", Age.ToString()) // only a string filter... 
     } 
    } 
} 

然後,您的視圖模型中有一個PersonFilter對象實例。

ICollectionViewFilter<Person> personFilter = new PersonFilter(); 

然後你只需在視圖模型中使用的CollectionViewFilter事件的一些方法,如:

CollectionView.Filter += FilterPeople 

private void FilterPeople(object obj) 
{ 
    var person = obj as Person; 
    if(person == null) 
     return false; 
    return personFilter.FilterObject(person); 
} 

篩選器名稱必須是相同的過濾屬性名稱目的。 :)

當然,您必須在某處撥打CollectionView.Refresh();,您可以將其移動到過濾器(例如,當屬性發生變化時,您可以撥打CollectionView.Refresh()立即查看更改),您可以在事件處理程序,但是你想要的。

這很簡單,雖然性能可能會更好。除非您使用幾十個過濾器過濾一公噸數據,否則調整和使用片段時不應出現太多問題。 :)

相關問題