Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Multiple CollectionView with different filters on same collection

I'm using a an ObservableCollection with two ICollectionView for different filters.

One is for filtering messages by some type, and one is for counting checked messages. As you can see message filter and message count works OK, but when I'm un-checking the message disappear from the list (the count is still working).

BTW sorry for the long post, I wanted to include all relevant stuff.

The XAML Code:

<!-- 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" /> 

Screenshot: enter image description here

Code:

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

Code For un-check function

private void CheckBoxZone_Unchecked(object sender, RoutedEventArgs e) {     CheckBox chkZone = (CheckBox)sender;     ucSystemMessageVM.checkedMessageList.Refresh(); } 
like image 759
drtf Avatar asked May 19 '13 11:05

drtf


1 Answers

This answer helped me with this exact problem. The static CollectionViewSource.GetDefaultView(coll) method will always return the same reference for a given collection, so basing multiple collection views on the same reference will be counterproductive. By instantiating the view as follows:

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

The view can now be filtered/sorted/grouped independently of any others. Then you can apply your filtering.

I know it's been a couple months and you have probably solved your problem by now, but I ran across this question when I had the same problem so I figured I would add an answer.

like image 172
randcd Avatar answered Nov 11 '22 09:11

randcd