35

Sto utilizzando uno ObservableCollection con due ICollectionView per diversi filtri.Raccolta multipla WPFVisualizza con diversi filtri sulla stessa collezione

Uno è per filtrare i messaggi di qualche tipo e uno è per il conteggio dei messaggi controllati. Come si può vedere il filtro dei messaggi e il conteggio dei messaggi funziona bene, ma quando sto deselezionando il messaggio scompare dall'elenco (il conteggio funziona ancora).

BTW scusate per il post lungo, volevo includere tutte le cose rilevanti.

Il Codice 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" /> 

Screenshot: enter image description here

Codice:

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

Codice Per un-che funzione di ck

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

Dave questa non è tanto una risposta, ma può aiutarti in fondo alla strada. Recentemente ho eseguito alcuni lavori con contratto WPF, ma non sono riuscito a trovare la soluzione giusta per il filtro, il paging e l'ordinamento come volevo. Ho costruito questa classe generica. Ho pensato che ti sarebbe piaciuto curiosare. http://www.origin1.com/downloads/PagedObservableCollection.txt. ovviamente cambia l'ext. – origin1tech

risposta

68

This answer mi ha aiutato con questo problema esatto. Il metodo statico CollectionViewSource.GetDefaultView(coll) restituirà sempre lo stesso riferimento per una determinata raccolta, quindi basare più viste di raccolta sullo stesso riferimento sarà controproducente. Istanziando la visualizzazione come segue:

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

La visualizzazione può ora essere filtrata/filtrate/raggruppati indipendentemente da tutti gli altri. Quindi puoi applicare il tuo filtro.

So che sono passati un paio di mesi e probabilmente hai già risolto il problema, ma ho trovato questa domanda quando ho avuto lo stesso problema, quindi ho pensato di aggiungere una risposta.

+4

Grazie, in realtà questo è molto utile in quanto non sono riuscito a ottenere ciò ed è risultato con una brutta soluzione alternativa – drtf

+0

Ho riscontrato un problema con questo metodo: filteredView sembra non osservare messageList, quindi non reagisce a nessuna modifica alla raccolta di origine –

Problemi correlati