C# ObservableCollection到3个列表视图中的1个,具体取决于某些属性

C# ObservableCollection到3个列表视图中的1个,具体取决于某些属性,c#,listview,visual-studio-2013,binding,windows-store-apps,C#,Listview,Visual Studio 2013,Binding,Windows Store Apps,我目前有一个名为MyList的ObservableCollection,它绑定到listview上的itemsource。它还从MyList中添加和删除项目 我想要的是根据一些条件在每个listview中添加项目。更具体地说,如果属性Status为“是”,则项目应转到第一个listviewMyListview,如果属性MySecondListview为“否”,则转到第二个listviewMySecondListview,如果Status==”且属性Date是DateTime属性,则转到第三个li

我目前有一个名为
MyList
的ObservableCollection,它绑定到listview上的itemsource。它还从MyList中添加和删除项目

我想要的是根据一些条件在每个listview中添加项目。更具体地说,如果属性
Status
为“是”,则项目应转到第一个listview
MyListview
,如果属性
MySecondListview
为“否”,则转到第二个listview
MySecondListview
,如果Status==”且属性
Date
是DateTime属性,则转到第三个listview

我的主页代码是:

public sealed partial class MainPage : Page
    {
        private ObservableCollection<MyClass> MyList = new ObservableCollection<MyClass>();
        public MainPage()
        {
            this.InitializeComponent();
            DataContext = MyList;
        }
         private void Add_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            MyList.Add(new MyClass("Yes", new DateTime(2015, 5, 4)));
        }

        private void Delete_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            MyList.Remove((MyClass)MyListview.SelectedItem);
        }
    }

从MVVM的角度来看,您可能有3个ObservableCollection,其中每个集合代表每个listview。但“模型”将有一个统一的列表。正如注释中所建议的,要正确地使用一个ObservableCollection执行此操作,需要创建一个视图(至少要使用绑定) 我要说的是,最明显的解决方案往往是最不容易混淆的

public ObservableCollection<MyClass> MyFirstListCollection...
public ObservableCollection<MyClass> MySecondListCollection...
然后,ObservableCollections必须是“属性”,而不仅仅是数据成员,添加getter和setter非常简单 例如,如果您从一个视图模型开始,它看起来像(为了简单起见,我省略了很多代码,比如缺少在ctor中创建可观察集合):

最后,你的班级看起来是这样的

class MyModel {
     List<MyClass> MyUnifiedList;
}
classmymodel{
列出我的统一列表;
}
您可能希望使用某种事件来引起UI刷新。但从某种意义上说,我认为你的单一列表标准使问题变得复杂。我个人会有3张清单。仅仅因为它们是同一个对象并不意味着它们需要在同一个列表中。没有必要过度优化,相信我,你不会后悔的。 当然,当你需要改变某些东西时,你会刷新一切。
一般来说,您需要考虑MVVM,这样视图就可以在视图模型中显示信息,并且该模型实现了逻辑。实际做这项工作。(在合理的情况下)这不是一条硬性规定,但一些关于MVVM的阅读将有助于区分这些地方。允许模型刷新视图模型的方法有很多

啊。因此,我没有意识到这一点,但事实证明Winrt(即Windows应用商店应用程序)不支持在
ICollectionView
中进行过滤。似乎每次我转过身,我都会发现另一个XAML/WPF特性被Winrt莫名其妙地忽略了,这就是其中之一

因此,虽然在WPF中实现这一点很简单(只需创建一个
CollectionViewSource
对象,订阅
Filter
事件,并绑定到对象的
视图
),但在Winrt中这会变得有点麻烦

已经有一些相关的文章,包括一篇关于堆栈溢出的文章,它们提供了替代方案。例如:

  • 堆栈溢出:
第二个是一个非常复杂的实现,用于支持过滤和其他操作。对于您的目的来说,这是过分的,但您可能会发现将来您希望使用它包含的功能

第一个例子,虽然在规模上更适合你的问题,但处理问题的方式与我有所不同。特别是,它实现了一个
observeableCollection
子类,该子类又有一个视图。这使得它无法用于“一个集合,多个视图”场景

因此,我编写了一个
ObservableCollection
,它的思路相同,但它本身就是视图,并引用了
ObservableCollection
的一个独立实例。您可以使用这个类的任意多个实例,我称之为
FilteredObservableCollection
,同时仍然维护单个源集合。根据过滤器,当源集合更改时,每个视图将根据需要更新自身


在这种方法中(我的类以及我自己的类的原始灵感),绑定视图本身就是一个
可观察集合
。特别是,这不是一个只读集合。非常重要的是,这些“视图”对象的任何使用者都不要试图直接修改视图对象,即使他们可以。它们应该只显示对象

在这方面,上面的第二个链接更好,因为它实现了一个实际的
ICollectionView
接口,它解决了易变性问题。坦率地说,从代码维护的角度来看,这样做会更好,让它更清楚什么对象是真正的列表,什么对象只是视图

但事实是,这种方法更简单,也更容易实现。只要小心使用,你就不会受伤。:)


要理解的另一个非常重要的限制是,此实现不会根据过滤器逻辑的更改(即,如果您传递本身取决于某个可变状态的
谓词
)或显示数据的更改来更新查看的集合(即,如果过滤器正在检查的属性在一个或多个显示的数据项中被修改)

这些限制可以通过多种方式解决,但这样做会大大增加这个答案的复杂性。我想尽量让事情简单化。我希望仅仅指出这些限制就足够了,以确保如果遇到需要更被动的视图实现的情况,那么您知道这一限制,并且知道您必须扩展此解决方案以支持您的需求。

该类最终看起来是这样的:

public class FilteredObservableCollection<T> : ObservableCollection<T>
{
    private Predicate<T> _filter;

    public FilteredObservableCollection(ObservableCollection<T> source, Predicate<T> filter)
        : base(source.Where(item => filter(item)))
    {
        source.CollectionChanged += source_CollectionChanged;
        _filter = filter;
    }

    private void _Fill(ObservableCollection<T> source)
    {
        Clear();
        foreach (T item in source)
        {
            if (_filter(item))
            {
                Add(item);
            }
        }
    }

    private int this[T item]
    {
        get
        {
            int foundIndex = -1;
            for (int index = 0; index < Count; index++)
            {
                if (this[index].Equals(item))
                {
                    foundIndex = index;
                    break;
                }
            }
            return foundIndex;
        }
    }

    private void source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        ObservableCollection<T> source = (ObservableCollection<T>)sender;

        switch (e.Action)
        {
        case NotifyCollectionChangedAction.Add:
            foreach (T item in e.NewItems)
            {
                if (_filter(item))
                {
                    Add(item);
                }
            }
            break;

        case NotifyCollectionChangedAction.Move:
            // Without a lot more work maintaining the view state, it would be just as hard
            // to figure out where the moved item should go, as it would be to just regenerate
            // the whole view. So just do the latter.
            _Fill(source);
            break;

        case NotifyCollectionChangedAction.Remove:
            foreach (T item in e.OldItems)
            {
                // Don't bother looking for the item if it was filtered out
                if (_filter(item))
                {
                    Remove(item);
                }
            }
            break;

        case NotifyCollectionChangedAction.Replace:
            for (int index = 0; index < e.OldItems.Count; index++)
            {
                T item = (T)e.OldItems[index];
                if (_filter(item))
                {
                    int foundIndex = this[item];

                    if (foundIndex == -1)
                    {
                        // i.e. should never happen
                        throw new Exception("internal state failure. object not present, even though it should be.");
                    }

                    T newItem = (T)e.NewItems[index];

                    if (_filter(newItem))
                    {
                        this[foundIndex] = newItem;
                    }
                    else
                    {
                        RemoveAt(foundIndex);
                    }
                }
                else
                {
                    // The item being replaced wasn't in the filtered
                    // set of data. Rather than do the work to figure out
                    // where the new item should go, just repopulate the
                    // whole list. (Same reasoning as for Move event).
                    _Fill(source);
                }
            }
            break;

        case NotifyCollectionChangedAction.Reset:
            _Fill(source);
            break;
        }
    }
}
<Page
    x:Class="TestSO30038588ICollectionView.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestSO30038588ICollectionView"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

  <Page.Resources>
    <DataTemplate x:Key="myClassTemplate">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Status}"/>
        <TextBlock Text="{Binding Date}" Margin="20, 0, 0, 0"/>
      </StackPanel>
    </DataTemplate>
  </Page.Resources>
  <Viewbox>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Height="768" Width="1366">
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Button x:Name="Delete" Content="Delete"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="224"
              Grid.Row="0" Grid.Column="0"
              Click="Delete_Click"/>
      <Button x:Name="Toggle" Content="Toggle Yes/No"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="224"
              Grid.Row="1" Grid.Column="0"
              Click="Toggle_Click"/>
      <Button x:Name="AddYes" Content="Add Yes"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="1"
              Click="AddYes_Click"/>
      <Button x:Name="AddNo" Content="Add No"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="2"
              Click="AddNo_Click"/>
      <Button x:Name="AddEmpty" Content="Add Empty"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="3"
              Click="AddEmpty_Click"/>
      <ListView x:Name="AllElementsList"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="2" Grid.Column="0"
                ItemsSource="{Binding MyList}"/>
      <ListView x:Name="MyListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="1" Grid.RowSpan="2"
                ItemsSource="{Binding yesList}"/>
      <ListView x:Name="MySecondListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="2" Grid.RowSpan="2"
                ItemsSource="{Binding noList}"/>
      <ListView x:Name="MyThirdListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="3" Grid.RowSpan="2"
                ItemsSource="{Binding emptyList}"/>
    </Grid>
  </Viewbox>
</Page>
public sealed partial class MainPage : Page
{
    public ObservableCollection<MyClass> MyList { get; set; }
    public FilteredObservableCollection<MyClass> yesList { get; set; }
    public FilteredObservableCollection<MyClass> noList { get; set; }
    public FilteredObservableCollection<MyClass> emptyList { get; set; }

    public MainPage()
    {
        this.InitializeComponent();

        MyList = new ObservableCollection<MyClass>();
        yesList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "Yes");
        noList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "No");
        emptyList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "" && item.Date.Date == DateTime.Now.Date);

        DataContext = this;
    }

    private void AddYes_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("Yes", DateTime.Now));
    }

    private void AddNo_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("No", DateTime.Now));
    }

    private void AddEmpty_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("", DateTime.Now));
    }

    private void Delete_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Remove((MyClass)AllElementsList.SelectedItem);
    }

    private void Toggle_Click(object sender, RoutedEventArgs e)
    {
        MyClass oldItem = (MyClass)AllElementsList.SelectedItem,
            newItem = new MyClass(oldItem.Status == "Yes" ? "No" : (oldItem.Status == "No" ? "Yes" : ""), oldItem.Date);

        MyList[AllElementsList.SelectedIndex] = newItem;
    }
}
主页
代码如下所示:

public class FilteredObservableCollection<T> : ObservableCollection<T>
{
    private Predicate<T> _filter;

    public FilteredObservableCollection(ObservableCollection<T> source, Predicate<T> filter)
        : base(source.Where(item => filter(item)))
    {
        source.CollectionChanged += source_CollectionChanged;
        _filter = filter;
    }

    private void _Fill(ObservableCollection<T> source)
    {
        Clear();
        foreach (T item in source)
        {
            if (_filter(item))
            {
                Add(item);
            }
        }
    }

    private int this[T item]
    {
        get
        {
            int foundIndex = -1;
            for (int index = 0; index < Count; index++)
            {
                if (this[index].Equals(item))
                {
                    foundIndex = index;
                    break;
                }
            }
            return foundIndex;
        }
    }

    private void source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        ObservableCollection<T> source = (ObservableCollection<T>)sender;

        switch (e.Action)
        {
        case NotifyCollectionChangedAction.Add:
            foreach (T item in e.NewItems)
            {
                if (_filter(item))
                {
                    Add(item);
                }
            }
            break;

        case NotifyCollectionChangedAction.Move:
            // Without a lot more work maintaining the view state, it would be just as hard
            // to figure out where the moved item should go, as it would be to just regenerate
            // the whole view. So just do the latter.
            _Fill(source);
            break;

        case NotifyCollectionChangedAction.Remove:
            foreach (T item in e.OldItems)
            {
                // Don't bother looking for the item if it was filtered out
                if (_filter(item))
                {
                    Remove(item);
                }
            }
            break;

        case NotifyCollectionChangedAction.Replace:
            for (int index = 0; index < e.OldItems.Count; index++)
            {
                T item = (T)e.OldItems[index];
                if (_filter(item))
                {
                    int foundIndex = this[item];

                    if (foundIndex == -1)
                    {
                        // i.e. should never happen
                        throw new Exception("internal state failure. object not present, even though it should be.");
                    }

                    T newItem = (T)e.NewItems[index];

                    if (_filter(newItem))
                    {
                        this[foundIndex] = newItem;
                    }
                    else
                    {
                        RemoveAt(foundIndex);
                    }
                }
                else
                {
                    // The item being replaced wasn't in the filtered
                    // set of data. Rather than do the work to figure out
                    // where the new item should go, just repopulate the
                    // whole list. (Same reasoning as for Move event).
                    _Fill(source);
                }
            }
            break;

        case NotifyCollectionChangedAction.Reset:
            _Fill(source);
            break;
        }
    }
}
<Page
    x:Class="TestSO30038588ICollectionView.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestSO30038588ICollectionView"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

  <Page.Resources>
    <DataTemplate x:Key="myClassTemplate">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Status}"/>
        <TextBlock Text="{Binding Date}" Margin="20, 0, 0, 0"/>
      </StackPanel>
    </DataTemplate>
  </Page.Resources>
  <Viewbox>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Height="768" Width="1366">
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Button x:Name="Delete" Content="Delete"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="224"
              Grid.Row="0" Grid.Column="0"
              Click="Delete_Click"/>
      <Button x:Name="Toggle" Content="Toggle Yes/No"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="224"
              Grid.Row="1" Grid.Column="0"
              Click="Toggle_Click"/>
      <Button x:Name="AddYes" Content="Add Yes"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="1"
              Click="AddYes_Click"/>
      <Button x:Name="AddNo" Content="Add No"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="2"
              Click="AddNo_Click"/>
      <Button x:Name="AddEmpty" Content="Add Empty"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="3"
              Click="AddEmpty_Click"/>
      <ListView x:Name="AllElementsList"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="2" Grid.Column="0"
                ItemsSource="{Binding MyList}"/>
      <ListView x:Name="MyListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="1" Grid.RowSpan="2"
                ItemsSource="{Binding yesList}"/>
      <ListView x:Name="MySecondListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="2" Grid.RowSpan="2"
                ItemsSource="{Binding noList}"/>
      <ListView x:Name="MyThirdListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="3" Grid.RowSpan="2"
                ItemsSource="{Binding emptyList}"/>
    </Grid>
  </Viewbox>
</Page>
public sealed partial class MainPage : Page
{
    public ObservableCollection<MyClass> MyList { get; set; }
    public FilteredObservableCollection<MyClass> yesList { get; set; }
    public FilteredObservableCollection<MyClass> noList { get; set; }
    public FilteredObservableCollection<MyClass> emptyList { get; set; }

    public MainPage()
    {
        this.InitializeComponent();

        MyList = new ObservableCollection<MyClass>();
        yesList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "Yes");
        noList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "No");
        emptyList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "" && item.Date.Date == DateTime.Now.Date);

        DataContext = this;
    }

    private void AddYes_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("Yes", DateTime.Now));
    }

    private void AddNo_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("No", DateTime.Now));
    }

    private void AddEmpty_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("", DateTime.Now));
    }

    private void Delete_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Remove((MyClass)AllElementsList.SelectedItem);
    }

    private void Toggle_Click(object sender, RoutedEventArgs e)
    {
        MyClass oldItem = (MyClass)AllElementsList.SelectedItem,
            newItem = new MyClass(oldItem.Status == "Yes" ? "No" : (oldItem.Status == "No" ? "Yes" : ""), oldItem.Date);

        MyList[AllElementsList.SelectedIndex] = newItem;
    }
}
公共密封部分类主页面:第页
{
公共ObservableCollection MyList{get;set;}
公共筛选器可服务集合yesList{get;
public class FilteredObservableCollection<T> : ObservableCollection<T>
{
    private Predicate<T> _filter;

    public FilteredObservableCollection(ObservableCollection<T> source, Predicate<T> filter)
        : base(source.Where(item => filter(item)))
    {
        source.CollectionChanged += source_CollectionChanged;
        _filter = filter;
    }

    private void _Fill(ObservableCollection<T> source)
    {
        Clear();
        foreach (T item in source)
        {
            if (_filter(item))
            {
                Add(item);
            }
        }
    }

    private int this[T item]
    {
        get
        {
            int foundIndex = -1;
            for (int index = 0; index < Count; index++)
            {
                if (this[index].Equals(item))
                {
                    foundIndex = index;
                    break;
                }
            }
            return foundIndex;
        }
    }

    private void source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        ObservableCollection<T> source = (ObservableCollection<T>)sender;

        switch (e.Action)
        {
        case NotifyCollectionChangedAction.Add:
            foreach (T item in e.NewItems)
            {
                if (_filter(item))
                {
                    Add(item);
                }
            }
            break;

        case NotifyCollectionChangedAction.Move:
            // Without a lot more work maintaining the view state, it would be just as hard
            // to figure out where the moved item should go, as it would be to just regenerate
            // the whole view. So just do the latter.
            _Fill(source);
            break;

        case NotifyCollectionChangedAction.Remove:
            foreach (T item in e.OldItems)
            {
                // Don't bother looking for the item if it was filtered out
                if (_filter(item))
                {
                    Remove(item);
                }
            }
            break;

        case NotifyCollectionChangedAction.Replace:
            for (int index = 0; index < e.OldItems.Count; index++)
            {
                T item = (T)e.OldItems[index];
                if (_filter(item))
                {
                    int foundIndex = this[item];

                    if (foundIndex == -1)
                    {
                        // i.e. should never happen
                        throw new Exception("internal state failure. object not present, even though it should be.");
                    }

                    T newItem = (T)e.NewItems[index];

                    if (_filter(newItem))
                    {
                        this[foundIndex] = newItem;
                    }
                    else
                    {
                        RemoveAt(foundIndex);
                    }
                }
                else
                {
                    // The item being replaced wasn't in the filtered
                    // set of data. Rather than do the work to figure out
                    // where the new item should go, just repopulate the
                    // whole list. (Same reasoning as for Move event).
                    _Fill(source);
                }
            }
            break;

        case NotifyCollectionChangedAction.Reset:
            _Fill(source);
            break;
        }
    }
}
<Page
    x:Class="TestSO30038588ICollectionView.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestSO30038588ICollectionView"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

  <Page.Resources>
    <DataTemplate x:Key="myClassTemplate">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Status}"/>
        <TextBlock Text="{Binding Date}" Margin="20, 0, 0, 0"/>
      </StackPanel>
    </DataTemplate>
  </Page.Resources>
  <Viewbox>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Height="768" Width="1366">
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Button x:Name="Delete" Content="Delete"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="224"
              Grid.Row="0" Grid.Column="0"
              Click="Delete_Click"/>
      <Button x:Name="Toggle" Content="Toggle Yes/No"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="224"
              Grid.Row="1" Grid.Column="0"
              Click="Toggle_Click"/>
      <Button x:Name="AddYes" Content="Add Yes"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="1"
              Click="AddYes_Click"/>
      <Button x:Name="AddNo" Content="Add No"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="2"
              Click="AddNo_Click"/>
      <Button x:Name="AddEmpty" Content="Add Empty"
              HorizontalAlignment="Left" VerticalAlignment="Top"
              Height="116" Width="214"
              Grid.Row="0" Grid.Column="3"
              Click="AddEmpty_Click"/>
      <ListView x:Name="AllElementsList"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="2" Grid.Column="0"
                ItemsSource="{Binding MyList}"/>
      <ListView x:Name="MyListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="1" Grid.RowSpan="2"
                ItemsSource="{Binding yesList}"/>
      <ListView x:Name="MySecondListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="2" Grid.RowSpan="2"
                ItemsSource="{Binding noList}"/>
      <ListView x:Name="MyThirdListview"
                ItemTemplate="{StaticResource myClassTemplate}"
                HorizontalAlignment="Left" VerticalAlignment="Top"
                Grid.Row="1" Grid.Column="3" Grid.RowSpan="2"
                ItemsSource="{Binding emptyList}"/>
    </Grid>
  </Viewbox>
</Page>
public sealed partial class MainPage : Page
{
    public ObservableCollection<MyClass> MyList { get; set; }
    public FilteredObservableCollection<MyClass> yesList { get; set; }
    public FilteredObservableCollection<MyClass> noList { get; set; }
    public FilteredObservableCollection<MyClass> emptyList { get; set; }

    public MainPage()
    {
        this.InitializeComponent();

        MyList = new ObservableCollection<MyClass>();
        yesList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "Yes");
        noList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "No");
        emptyList = new FilteredObservableCollection<MyClass>(MyList, item => item.Status == "" && item.Date.Date == DateTime.Now.Date);

        DataContext = this;
    }

    private void AddYes_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("Yes", DateTime.Now));
    }

    private void AddNo_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("No", DateTime.Now));
    }

    private void AddEmpty_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Add(new MyClass("", DateTime.Now));
    }

    private void Delete_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    {
        MyList.Remove((MyClass)AllElementsList.SelectedItem);
    }

    private void Toggle_Click(object sender, RoutedEventArgs e)
    {
        MyClass oldItem = (MyClass)AllElementsList.SelectedItem,
            newItem = new MyClass(oldItem.Status == "Yes" ? "No" : (oldItem.Status == "No" ? "Yes" : ""), oldItem.Date);

        MyList[AllElementsList.SelectedIndex] = newItem;
    }
}