35

Ich verwende eine ObservableCollection mit zwei ICollectionView für verschiedene Filter.WPF Multiple CollectionView mit verschiedenen Filtern für die gleiche Sammlung

Einer ist für das Filtern von Nachrichten von einem Typ, und einer ist für das Zählen von überprüften Nachrichten. Wie Sie sehen, Nachrichtenfilter und Nachricht Anzahl funktioniert OK, aber wenn ich die Überprüfung deaktivieren, verschwinden die Nachricht aus der Liste (die Anzahl funktioniert immer noch).

BTW Entschuldigung für die lange Post, ich wollte alle relevanten Sachen enthalten.

Der 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 Für un-che ck Funktion

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

Dave das ist nicht so eine Antwort, aber kann Ihnen helfen, die Straße hinunter. Vor kurzem habe ich einige WPF-Vertragsarbeiten erledigt. Ich konnte einfach nicht die richtige Lösung für Filter, Paging und Sortierung finden, wie ich es wollte. Ich habe diese generische Klasse erstellt. Ich dachte, du möchtest vielleicht darin herumstochern. http://www.origin1.com/downloads/PagedObservableCollection.txt. Offensichtlich ändern die ext. – origin1tech

Antwort

68

This answer half mir mit genau diesem Problem. Die statische Methode CollectionViewSource.GetDefaultView(coll) gibt immer den gleichen Verweis für eine bestimmte Sammlung zurück, so dass mehrere Sammlungsansichten auf dieselbe Referenz basieren, ist kontraproduktiv. Durch Instanziierung der Ansicht wie folgt:

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

Der Blick jetzt gefiltert werden kann/sortiert/unabhängig von irgendwelchen anderen gruppiert. Dann können Sie Ihre Filterung anwenden.

Ich weiß, dass es ein paar Monate gedauert hat und Sie wahrscheinlich Ihr Problem gelöst haben, aber ich bin über diese Frage gestolpert, als ich das gleiche Problem hatte, also dachte ich, ich würde eine Antwort hinzufügen.

+4

Danke, das ist wirklich sehr hilfreich, da ich das nicht erreichen konnte und mit einer großen hässlichen Problemumgehung endete. – drtf

+0

Ich habe ein Problem mit dieser Methode: filteredView scheint keine messageList zu beobachten, also reagiert es nicht auf irgendeine Änderung der Quellensammlung –