WPF在同一集合上具有不同过滤器的多个集合视图

时间:2022-09-12 08:39:28

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

我正在使用一个带有两个ICollectionView的天文台来处理不同的过滤器。

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:

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: WPF在同一集合上具有不同过滤器的多个集合视图

截图:

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();
}

1 个解决方案

#1


70  

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:

这个答案帮助我解决了这个问题。静态CollectionViewSource.GetDefaultView(coll)方法将始终返回给定集合的相同引用,因此基于同一引用的多个集合视图将会产生反效果。通过实例化视图如下:

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.

我知道已经有几个月了,你可能已经解决了你的问题,但是我遇到同样的问题时遇到了这个问题,所以我想我应该加上一个答案。

#1


70  

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:

这个答案帮助我解决了这个问题。静态CollectionViewSource.GetDefaultView(coll)方法将始终返回给定集合的相同引用,因此基于同一引用的多个集合视图将会产生反效果。通过实例化视图如下:

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.

我知道已经有几个月了,你可能已经解决了你的问题,但是我遇到同样的问题时遇到了这个问题,所以我想我应该加上一个答案。