CollectionView:过滤器在绑定到e时不起作用。 G。列表框

时间:2015-06-15 21:25:37

标签: c# wpf

我有一些包含音符的级联容器,其中有一个主容器,其中包含所有音符。 notes容器是在树状结构中制作的,在树形结构中越深越具体。我只有一个列表的原因与数据的非常复杂的管理有关,而不是问题的一部分。

主注释容器有一个ObservableCollection,所有子注释容器都通过CollectionView绑定到ObservableCollection。子笔记容器有一个过滤器,可以过滤掉它们的笔记。在常规代码中,一切正常,视图总是显示元素,但是当我将它们绑定到e时。 G。 ListBox,元素不会被过滤,主列表中的所有元素都会在没有过滤的情况下显示。当然我知道有一个ListCollectionView,但由于CollectionView来自IEnumerable,我很好奇ListBox如何访问主列表,如果它不从CollectionView访问SourceCollection。

换句话说,我不太清楚为什么我需要ListCollectionView来实现ColletionView适合的非常基本的行为。在我看来,ListCollectionView是必需的,而其他视图真的不适合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);
        }
    }
}

由于 马丁

1 个答案:

答案 0 :(得分:3)

CollectionView class文档备注部分的第一行说:

  

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

所以,我猜它可能不是按照你使用它的方式设计的。

我总是使用CollectionViewSource.GetDefaultView(collection)(最终会为ListCollectionView返回ObservableCollection<T>,但会以ICollectionView的形式返回。

编辑:希望清楚一些事情,这里有一些关于集合视图的其他信息。

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

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

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

从Viewmodel代码创建

创建一个新的ListCollectionView,将集合传递给构造函数。如果您在viewmodel代码中,则可以将视图公开为属性(通常为ICollectionView类型)。

Viewmodel代码:

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视图创建

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

Viewmodel代码:

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>