ICollectionView Issue

David McCallum 51 Reputation points
2022-05-01T10:36:28.28+00:00

I have two ICollectionViews bound to two xaml ListBoxes

If I remove the Filter assignment, I get image 1 (to be expected, but leaving them in gives nothing in the ListBox, I would expect the left one to be populated as all data has Selected = false;

Am I missing something?

using System.Collections.Generic;  
using System.ComponentModel;  
using System.Windows.Data;  
using Microsoft.Toolkit.Mvvm.ComponentModel;  
// ReSharper disable MemberCanBePrivate.Global  
  
namespace UserControls.DualListUserControls;  
  
public abstract class AbstractDualListViewModel<T> : ObservableObject where T : IDisplayString  
{  
    protected AbstractDualListViewModel(IEnumerable<T> sourceList)  
    {  
        Source = CollectionViewSource.GetDefaultView(sourceList);  
        Source.Filter += FalseFilter;  
        Source.Refresh();  
        Destination = CollectionViewSource.GetDefaultView(sourceList);  
        Source.Filter += TrueFilter;  
        Destination.Refresh();  
    }  
  
    public ICollectionView Destination { get; set; }  
  
    public ICollectionView Source { get; set; }  
  
    private bool TrueFilter(object obj)  
    {  
        var ids = (T) obj;  
        return ids.Selected;  
    }  
  
    private bool FalseFilter(object obj)  
    {  
        var ids = (T) obj;  
        return !ids.Selected;  
    }  
}  

198022-image.png
197924-image.png

Developer technologies XAML
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,676 Reputation points Microsoft External Staff
    2022-05-03T07:55:59.567+00:00

    If you want to filter by Selected, bind the ICollectionView of Selected=false data to the ListBox on the left, and bind the ICollectionView of Selected=true data to the ListBox on the right, you could try to use the following method.
    UserControl1.xaml:

    <Grid>  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition Width="*" />  
            <ColumnDefinition Width="Auto" />  
            <ColumnDefinition Width="*" />  
        </Grid.ColumnDefinitions>  
        <ScrollViewer Grid.Column="0" VerticalScrollBarVisibility="Auto">  
            <ListBox   ItemsSource="{Binding Source}">  
                <ListBox.ItemTemplate>  
                    <DataTemplate>  
                        <CheckBox  IsChecked="{Binding Selected, Mode=TwoWay}"  
                    Content="{Binding DisplayString}"/>  
                    </DataTemplate>  
                </ListBox.ItemTemplate>  
            </ListBox>  
        </ScrollViewer>  
        <StackPanel Grid.Column="1" VerticalAlignment="Center">  
            <Button Content="&lt;" />  
            <Button Content="&lt;&lt;"  />  
            <Button Content="&gt;" />  
            <Button Content="&gt;&gt;"  />  
        </StackPanel>  
        <ScrollViewer Grid.Column="2" VerticalScrollBarVisibility="Auto">  
            <ListBox    ItemsSource="{Binding Destination}"  >  
                <ListBox.ItemTemplate>  
                    <DataTemplate>  
                        <CheckBox  IsChecked="{Binding Selected, Mode=TwoWay}"  
                    Content="{Binding DisplayString}"/>  
                    </DataTemplate>  
                </ListBox.ItemTemplate>  
            </ListBox>  
        </ScrollViewer>  
      
    </Grid>  
    

    UserControl1.xaml.cs:

    using System;  
    using System.Collections.Generic;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Runtime.CompilerServices;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
      
    namespace UserControl1  
    {  
      public partial class UserControl1 : UserControl  
      {  
        SampleDualListViewModel vm;  
        public UserControl1()  
        {  
          InitializeComponent();  
          vm=new SampleDualListViewModel();  
          this.DataContext=vm;  
      
        }  
      }  
      public class SampleDualListViewModel  
      {  
        SampleData sampleData;  
        public ICollectionView Destination { get; set; }  
        public ICollectionView Source { get; set; }  
        public CollectionViewSource CvsSelected{ get;set;}  
        public CollectionViewSource CvsNotSelected{ get;set;}  
        private ObservableCollection<SampleData> data;  
        public ObservableCollection<SampleData> Data   
        {  
          get { return data; }  
          set  
          {  
            data = value;  
          }  
        }  
        public IEnumerable<SampleData> Items { get { return data; } }  
        public SampleDualListViewModel()  
        {  
          data = new ObservableCollection<SampleData>();  
          for (int i = 0; i< 20; i++)  
            {  
              sampleData = new SampleData(){ DisplayString= $"Line {i}", Selected= i % 2 == 0 };  
              data.Add(sampleData);  
            }  
          CvsSelected = new CollectionViewSource();  
          CvsSelected.Source=Data;  
          CvsSelected.Filter += (s, e) =>  
          {  
            SampleData sd=e.Item as SampleData;  
            e.Accepted = sd.Selected;  
          };  
          Destination = CvsSelected.View;  
          Destination.Refresh();  
      
          CvsNotSelected = new CollectionViewSource();  
          CvsNotSelected.Source = Data;  
          CvsNotSelected.Filter += (s, e) =>  
          {  
            SampleData sd = e.Item as SampleData;  
            e.Accepted = !sd.Selected;  
          };  
          Source = CvsNotSelected.View;  
          Source.Refresh();  
        }  
      
      }  
         
        public class SampleData : INotifyPropertyChanged  
      {  
        public SampleData() { }  
        public SampleData(string s)  
        {  
          DisplayString = s;  
        }  
        private string displayString;  
        public string DisplayString   
        {  
          get { return displayString; }  
          set  
          {  
            displayString = value;  
            OnPropertyChanged("DisplayString");  
          }  
        }  
        private bool selected;  
        public bool Selected  
        {  
          get { return selected; }  
          set  
          {  
            selected = value;  
            OnPropertyChanged("Selected");  
          }  
        }  
        public event PropertyChangedEventHandler PropertyChanged;  
        protected void OnPropertyChanged([CallerMemberName] string name = null)  
        {  
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));  
        }  
      }  
    }  
    

    MainWindow.xaml:(Test)

     <Window x:Class="Test.MainWindow"  
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
                xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
                xmlns:local="clr-namespace:Test"  
                xmlns:dualListUserControls="clr-namespace:UserControls.DualListUserControls;assembly=UserControls"  
                xmlns:uc="clr-namespace:UserControl1;assembly=UserControl1"  
                mc:Ignorable="d"  
                Title="MainWindow" Height="407" Width="300">  
          
            <StackPanel >  
                <uc:UserControl1  Height="300" />  
            </StackPanel>  
        </Window>  
    

    The result:
    198463-image.png


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. David McCallum 51 Reputation points
    2022-05-02T10:39:29.247+00:00

    s!AoEHbi5A2zZel_gSzzIMIXfzLj_C7A

    Here is a link to the whole solution, UserControl library and test project:

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.