35

Używam ObservableCollection z dwoma ICollectionView dla różnych filtrów.WPF Multiple CollectionView z różnymi filtrami w tej samej kolekcji

Jedna służy do filtrowania wiadomości według typów, a druga do zliczania sprawdzanych wiadomości. Jak widać filtr wiadomości i liczba wiadomości działa OK, ale kiedy jestem un-sprawdzanie wiadomość zniknie z listy (licznik nadal działa).

BTW przepraszam za długi post, chciałem dołączyć wszystkie istotne rzeczy.

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

Zrzut ekranu: enter image description here

Kod:

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

Kod UN-Che Funkcja ck

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

Dave to nie jest odpowiedź, ale może pomóc w dół. Niedawno wykonując niektóre prace kontraktowe WPF po prostu nie mogłem znaleźć odpowiedniego rozwiązania do filtrowania, przywoływania, sortowania, jak tego chciałem. Zbudowałem tę ogólną klasę. Pomyślałem, że możesz w to wskoczyć. http://www.origin1.com/downloads/PagedObservableCollection.txt. oczywiście zmień ext. – origin1tech

Odpowiedz

68

This answer pomógł mi z dokładnym tego problemu. Metoda statyczna CollectionViewSource.GetDefaultView(coll) zawsze zwróci to samo odwołanie dla danej kolekcji, więc oparcie wielu widoków kolekcji na tym samym odwołaniu przyniesie efekt odwrotny do zamierzonego. Tworząc instancję widoku w następujący sposób:

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

Widok można teraz filtrować/sortować/grupować niezależnie od innych. Następnie możesz zastosować filtrowanie.

Wiem, że minęło już kilka miesięcy i prawdopodobnie rozwiązałeś już swój problem, ale natknąłem się na to pytanie, gdy miałem ten sam problem, więc pomyślałem, że dodam odpowiedź.

+4

Dzięki, w rzeczywistości jest to bardzo pomocne, ponieważ nie mogłem tego osiągnąć i wynikło z dużym brzydkim obejściem problemu. – drtf

+0

Mam problem z tą metodą: filterView wydaje się nie obserwować elementu messageList, więc nie reaguje na żadne zmiany w kolekcji źródłowej –

Powiązane problemy