我有一些包含笔记的级联容器,其中有一个包含所有笔记的主容器。笔记容器是在树状层次结构中制作的,树结构越深,层次结构就越具体。我只有一个列表的原因与非常复杂的数据管理有关,这不是问题的一部分。
主笔记容器有一个ObservableCollection
,所有子笔记容器都通过CollectionView
绑定(bind)到ObservableCollection
。子笔记容器有一个过滤器可以过滤掉他们的笔记。在常规代码中,一切正常, View 始终显示元素,但是当我将它们绑定(bind)到 e. G。 ListBox
,元素未被过滤,主列表中的所有元素均未过滤显示。我当然知道有一个 ListCollectionView
,但由于 CollectionView 来自 IEnumerable
,我很好奇 ListBox
是如何访问主列表的,如果它不从 CollectionView
访问 SourceCollection
。
换句话说,我不太清楚为什么我需要 ListCollectionView
来实现 ColletionView
应该适合的非常基本的行为。在我看来,ListCollectionView
是强制性的,而不是其他 View 真的适合 ListBox
?
这是一个小例子
XAML:
<Window x:Class="ListCollection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Horizontal">
<ListBox Width="100" ItemsSource="{Binding Model}"></ListBox>
<ListBox Width="100" ItemsSource="{Binding View1}"></ListBox>
<ListBox Width="100" ItemsSource="{Binding View2}"></ListBox>
</StackPanel>
</Window>
C#:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
namespace ListCollection
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ObservableCollection<int> Model
{
get; private set;
}
public ICollectionView View1
{
get; private set;
}
public ICollectionView View2
{
get; private set;
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
Model = new ObservableCollection<int>();
View1 = new CollectionView(Model);
View1.Filter = (o) =>
{
return ((int)o) > 50;
};
View2 = new CollectionView(View1);
View2.Filter = (o) =>
{
return ((int)o) > 70;
};
for (int i = 0; i < 100; i++)
Model.Add(i);
}
}
}
谢谢 马丁
请您参考如下方法:
CollectionView class 文档备注部分的第一行说:
You should not create objects of this class in your code.
所以,我猜它可能不是按照您的使用方式设计的。
我总是使用 CollectionViewSource.GetDefaultView(collection)
(最终会为 ListCollectionView
返回一个 ObservableCollection<T>
,但它返回为一个 ICollectionView
)。
编辑:为了澄清一些事情,这里有一些关于 Collection View 的附加信息。
在 Data Binding Overview 上有一个相当不错的 Collection View 概述。文档页面,这是一个很好的阅读。它解释了为什么每个集合有一个默认 View 。每当将集合用作数据绑定(bind)的源时,它就会由框架创建。 GetDefaultView
方法获取该 View (如果它不存在则创建它)。对该方法的后续调用将始终返回相同的 View 。
如果你绑定(bind)一个 ItemsControl.ItemsSource
直接到一个集合,它将使用默认 View 。因此,绑定(bind)到默认 View 和绑定(bind)到集合本身具有相同的结果。如果您希望将多个 View 放入同一个集合中,那么您将需要创建自己的 Collection View 并显式绑定(bind)到这些 View ,而不是绑定(bind)到集合或默认 View 。
有几种创建 Collection View 的方法,具体取决于您是从代码还是 xaml 创建它们。
从 Viewmodel 代码创建
创建一个新的 ListCollectionView
,将集合传递给构造函数。如果您在 View 模型代码中,则可以将 View 公开为属性(通常类型为 ICollectionView
)。
查看模型代码:
private ObservableCollection<Item> mItems;
public ICollectionView MyView { get; private set; }
public MyVM()
{
mItems = new ObservableCollection<Item>();
ListCollectionView myView = new ListCollectionView(mItems);
// Do whatever you want with the view here
MyView = myView;
}
查看代码:
<ItemsControl ItemsSource="{Binding MyView}" />
从 XAML View 创建
创建一个 CollectionViewSource
并设置它的 Source
集合的属性。您还可以设置其他属性,例如 Filter
,它将调用代码隐藏来运行过滤器。
查看模型代码:
private ObservableCollection<Item> mItems;
public IEnumerable<Item> Items { get { return mItems; } }
public MyVM()
{
mItems = new ObservableCollection<Item>();
}
查看代码:
<Grid>
<Grid.Resources>
<CollectionViewSource
x:Key="MyItemsSource"
Source="{Binding Items}" />
</Grid.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource MyItemsSource}}" />
</Grid>