CollectionView:绑定到例如 ListBox 时过滤器不起作用

mse*_*edi 2 c# wpf xaml

我有某种包含笔记的级联容器,其中有一个主容器包含所有笔记。笔记容器以树状层次结构形式制作,树结构越深入,笔记容器就越具体。我只有一个列表的原因与非常复杂的数据管理有关,但这不是问题的一部分。

\n\n

主注释容器有一个ObservableCollection,所有子注释容器都绑定到ObservableCollectionvia CollectionView。子注释容器有一个过滤器,可以过滤掉它们的注释。在常规代码中,一切正常,视图始终显示元素,但是当我将它们绑定到 eg 时ListBox,元素不会被过滤,并且主列表中的所有元素都会显示而不进行过滤。当然我知道有一个ListCollectionView,但是由于 CollectionView 来自IEnumerable,我很好奇如果它ListBox不从 访问 ,那么它如何访问主SourceCollection列表CollectionView

\n\n

换句话说,我不太确定为什么我需要应该适合的ListCollectionView非常基本的行为ColletionView。在我看来, 是ListCollectionView强制性的,而不是其他观点真正适合ListBox

\n\n

这是一个小样本

\n\n

XAML:

\n\n
<Window x:Class="ListCollection.MainWindow"\n        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n        Title="MainWindow" Height="350" Width="525">\n    <StackPanel Orientation="Horizontal">\n        <ListBox Width="100" ItemsSource="{Binding Model}"></ListBox>\n        <ListBox Width="100" ItemsSource="{Binding View1}"></ListBox>\n        <ListBox Width="100" ItemsSource="{Binding View2}"></ListBox>\n    </StackPanel>\n</Window>\n
Run Code Online (Sandbox Code Playgroud)\n\n

C#:

\n\n
using System.Collections.ObjectModel;\nusing System.ComponentModel;\nusing System.Windows;\nusing System.Windows.Data;\n\nnamespace ListCollection\n{\n    /// <summary>\n    /// Interaktionslogik f\xc3\xbcr MainWindow.xaml\n    /// </summary>\n    public partial class MainWindow : Window\n    {\n        public ObservableCollection<int> Model\n        {\n            get; private set;\n        }\n\n        public ICollectionView View1\n        {\n            get; private set;\n        }\n\n        public ICollectionView View2\n        {\n            get; private set;\n        }\n\n        public MainWindow()\n        {\n            InitializeComponent();\n\n            DataContext = this;\n\n            Model = new ObservableCollection<int>();\n            View1 = new CollectionView(Model);\n            View1.Filter = (o) =>\n            {\n                return ((int)o) > 50;\n            };\n\n            View2 = new CollectionView(View1);\n            View2.Filter = (o) =>\n            {\n                return ((int)o) > 70;\n            };\n\n            for (int i = 0; i < 100; i++)\n                Model.Add(i);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

谢谢\n马丁

\n

Xav*_*ier 5

CollectionView 类文档备注部分的第一行内容如下:

您不应在代码中创建此类的对象。

所以,我猜它可能不是为您使用它的方式而设计的。

我总是使用CollectionViewSource.GetDefaultView(collection)(最终会返回一个ListCollectionViewfor ObservableCollection<T>,但它作为一个返回ICollectionView)。


编辑:为了希望澄清一些事情,这里有一些有关集合视图的附加信息。

数据绑定概述文档页面上有一个相当不错的集合视图概述,值得一读。它解释了为什么每个集合都有一个默认视图。每当集合用作数据绑定源时,框架都会创建它。该GetDefaultView方法获取该视图(如果尚不存在则创建它)。对该方法的后续调用将始终返回相同的视图。

如果将 anItemsControl.ItemsSource直接绑定到集合,它将使用默认视图。因此,绑定到默认视图和绑定到集合本身具有相同的结果。如果您希望同一集合中有多个视图,那么您将需要创建自己的集合视图并显式绑定到这些视图,而不是绑定到集合或默认视图。

有多种方法可以创建集合视图,具体取决于您是从代码还是 xaml 创建它们。

从 Viewmodel 代码创建

创建一个新的ListCollectionView,将集合传递给构造函数。如果您使用视图模型代码,则可以将视图公开为属性(通常为 类型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;
}
Run Code Online (Sandbox Code Playgroud)

查看代码:

<ItemsControl ItemsSource="{Binding MyView}" />
Run Code Online (Sandbox Code Playgroud)

从 XAML 视图创建

创建一个集合CollectionViewSource并将其Source属性设置为集合。您还可以设置其他属性,例如Filter,它将调用隐藏代码来运行过滤器。

视图模型代码:

private ObservableCollection<Item> mItems;
public IEnumerable<Item> Items { get { return mItems; } }

public MyVM()
{
    mItems = new ObservableCollection<Item>();
}
Run Code Online (Sandbox Code Playgroud)

查看代码:

<Grid>
    <Grid.Resources>
        <CollectionViewSource
            x:Key="MyItemsSource"
            Source="{Binding Items}" />
    </Grid.Resources>
    <ItemsControl ItemsSource="{Binding Source={StaticResource MyItemsSource}}" />
</Grid>
Run Code Online (Sandbox Code Playgroud)