35

對於不同的過濾器,我使用的是ObservableCollection和兩個ICollectionViewWPF在同一集合上使用不同過濾器的多個CollectionView

一個用於按某種類型過濾郵件,另一個用於計算檢查的郵件。 正如你所看到的消息過濾器和消息計數工作正常,但是當我不檢查消息從列表中消失(計數仍在工作)。

順便說一句,很抱歉,我想包括所有相關的東西。

的XAML代碼:

<!-- Messages List --> 
<DockPanel Grid.Row="1" 
      Grid.Column="0" 
      Grid.ColumnSpan="3" 
      Height="500"> 
    <ListBox Name="listBoxZone" 
      ItemsSource="{Binding filteredMessageList}" 
      Background="Transparent" 
      BorderThickness="0"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
     <CheckBox Name="CheckBoxZone" 
        Content="{Binding text}" 
        Tag="{Binding id}" 
        Unchecked="CheckBoxZone_Unchecked" 
        Foreground="WhiteSmoke" 
        Margin="0,5,0,0" 
        IsChecked="{Binding isChecked}" /> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
    </ListBox> 
</DockPanel> 
<Button Content="Test Add New" 
     Grid.Column="2" 
     Height="25" 
     HorizontalAlignment="Left" 
     Margin="34,2,0,0" 
     Click="button1_Click" /> 
<Label Content="{Binding checkedMessageList.Count}" 
     Grid.Column="2" 
     Height="25" 
     Margin="147,2,373,0" 
     Width="20" 
     Foreground="white" /> 

截圖: enter image description here

代碼:

/* ViewModel Class */ 
public class MainViewModel : INotifyPropertyChanged 
{ 

    // Constructor 
    public MainViewModel() 
    { 
     #region filteredMessageList 
     // connect the ObservableCollection to CollectionView 
     _filteredMessageList = CollectionViewSource.GetDefaultView(messageList); 
     // set filter 
     _filteredMessageList.Filter = delegate(object item) 
     { 
      MessageClass temp = item as MessageClass; 

      if (selectedFilter.Equals(AvailableFilters.All)) 
      { 
       return true; 
      } 
      else 
      { 
       return temp.filter.Equals(_selectedFilter); 
      } 
     }; 
     #endregion 

     #region checkedMessageList 
     // connect the ObservableCollection to CollectionView 
     _checkedMessageList = CollectionViewSource.GetDefaultView(messageList); 
     // set filter 
     _checkedMessageList.Filter = delegate(object item) { return (item as MessageClass).isChecked; }; 
     #endregion 
    } 

    // message List 
    private ObservableCollection<MessageClass> _messageList = 
      new ObservableCollection<MessageClass>(); 
    public ObservableCollection<MessageClass> messageList 
    { 
     get { return _messageList; } 
     set { _messageList = value; } 
    } 

    // CollectionView (filtered messageList) 
    private ICollectionView _filteredMessageList; 
    public ICollectionView filteredMessageList 
    { 
     get { return _filteredMessageList; } 
    } 

    // CollectionView (filtered messageList) 
    private ICollectionView _checkedMessageList; 
    public ICollectionView checkedMessageList 
    { 
     get { return _checkedMessageList; } 
    } 

    // SelectedFilter property 
    private AvailableFilters _selectedFilter = AvailableFilters.All; // Default is set to all 
    public AvailableFilters selectedFilter 
    { 
     get { return _selectedFilter; } 
     set 
     { 
      _selectedFilter = value; 
      RaisePropertyChanged("selectedFilter"); 
      _filteredMessageList.Refresh(); // refresh list upon update 
     } 
    } 

    // FilterList (Convert Enum To Collection) 
    private List<KeyValuePair<string, AvailableFilters>> _AvailableFiltersList; 
    public List<KeyValuePair<string, AvailableFilters>> AvailableFiltersList 
    { 
     get 
     { 
      /* Check if such list available, if not create for first use */ 
      if (_AvailableFiltersList == null) 
      { 
       _AvailableFiltersList = new List<KeyValuePair<string, AvailableFilters>>(); 
       foreach (AvailableFilters filter in Enum.GetValues(typeof(AvailableFilters))) 
       { 
        string Description; 
        FieldInfo fieldInfo = filter.GetType().GetField(filter.ToString()); 
        DescriptionAttribute[] attributes = 
           (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 

        /* if not null get description */ 
        if (attributes != null && attributes.Length > 0) 
        { 
         Description = attributes[0].Description; 
        } 
        else 
        { 
         Description = string.Empty; 
        } 

        /* add as new item to filterList */ 
        KeyValuePair<string, AvailableFilters> TypeKeyValue = 
           new KeyValuePair<string, AvailableFilters>(Description, filter); 

        _AvailableFiltersList.Add(TypeKeyValue); 
       } 
      } 
      return _AvailableFiltersList; 
     } 
    } 

    #region Implement INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 
    public void RaisePropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    #endregion 
} 

代碼對於聯合國枝CK功能

private void CheckBoxZone_Unchecked(object sender, RoutedEventArgs e) 
{ 
    CheckBox chkZone = (CheckBox)sender; 
    ucSystemMessageVM.checkedMessageList.Refresh(); 
} 
+0

戴夫這不是一個答案,但可能會幫助你的道路。最近做了一些WPF合同工作,我無法找到正確的解決方案來篩選,分頁,按照我的意願進行排序。我建立了這個通用類。以爲你可能喜歡在它周圍徘徊。 http://www.origin1.com/downloads/PagedObservableCollection.txt。明顯改變分機。 – origin1tech

回答

68

This answer幫我這個確切的問題。靜態的CollectionViewSource.GetDefaultView(coll)方法將始終返回給定集合的相同引用,因此基於同一個引用的多個集合視圖會適得其反。通過實例化視圖如下:

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

視圖現在可以過濾/分類/獨立於任何其他的分組。然後你可以應用你的過濾。

我知道這已經過去了幾個月,現在你可能已經解決了你的問題,但是當我遇到同樣的問題時,我碰到了這個問題,所以我想我會添加一個答案。

+4

謝謝,其實這是非常有用的,因爲我無法實現這一點,並導致了一個很大的醜陋解決方法 – drtf

+0

我有這個方法的問題:filteredView似乎不遵守messageList,所以它不會對源集合的任何更改作出反應 –

相關問題