C# 如何将ObservableCollection的前N项绑定到ItemsControl?

C# 如何将ObservableCollection的前N项绑定到ItemsControl?,c#,wpf,observablecollection,C#,Wpf,Observablecollection,我想将ObservableCollection的前N个项绑定到ItemsControl 我尝试过这个解决方案: 这是我的代码: XAML: 代码隐藏: using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Linq;

我想将ObservableCollection的前N个项绑定到ItemsControl

我尝试过这个解决方案:

这是我的代码:
XAML:


代码隐藏:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            IC.ItemsSource = CM.TopCollection;
        }
        CollectionModel CM = new CollectionModel();
        public class TestModel {
            public string ABC { get; set; }
        }
        public class CollectionModel : ObservableCollection<TestModel>, INotifyPropertyChanged
        {
            public CollectionModel()
            {
                CollectionChanged += MyCollection_CollectionChanged;
            }          

            private void MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {   // to notify XAML-side binding
                OnPropertyChanged(new PropertyChangedEventArgs(nameof(TopCollection)));
            }
            public IEnumerable<TestModel> TopCollection => this.Take(10);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            CM.Add(new TestModel() {ABC= Guid.NewGuid().ToString() });
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.Collections.Specialized;
使用系统组件模型;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间WpfApp1
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
IC.ItemsSource=CM.TopCollection;
}
CollectionModel CM=新的CollectionModel();
公共类测试模型{
公共字符串ABC{get;set;}
}
公共类集合模型:ObservableCollection,INotifyPropertyChanged
{
公共集合模型()
{
CollectionChanged+=MyCollection\u CollectionChanged;
}          
私有void MyCollection\u CollectionChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{//通知XAML端绑定
OnPropertyChanged(新PropertyChangedEventArgs(名称)(TopCollection));
}
public IEnumerable TopCollection=>this.Take(10);
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
Add(newtestmodel(){ABC=Guid.NewGuid().ToString()});
}
}
}
我按了一下按钮。但是,
CM
成功添加了新项目,但用户界面没有更新任何项目

为什么结果是这样

我使用断点进行测试,发现
CollectionChanged
&
OnPropertyChanged
都工作正常。但是为什么UI仍然没有更新?


你能帮帮我吗?谢谢。

您需要绑定到
CollectionModel
TopCollection
属性,才能使
PropertyChanged
事件生效:

public MainWindow()
{
    InitializeComponent();
    DataContext = CM;
    IC.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("TopCollection"));
}
如果将
DataContext
设置为实现
INotifyPropertyChanged
CollectionModel
,则可以在XAML标记中执行此操作:

<ItemsControl x:Name="IC" ItemsSource="{Binding TopCollection}" ... />

您的收集模型是一个可观察的收集,您做得非常正确。这意味着,当添加/删除项目时,它将引发事件(供订阅者观察和处理)

然而,您实际绑定到的“TopCollection”只是一个IEnumerable。简而言之,它不会引发使其完全数据绑定的事件


您需要公开TopCollection的ObservableCollection。然后,您可以在其基础数据源更改时,甚至仅在其筛选结果更改时引发事件。

现在,您只需设置ItemsSource一次。但您需要在更新实际的支持数据后进行更新。通常,这是通过
绑定来完成的(您在上面的代码中也部分使用了绑定)。。。理论上可以由一些附加属性或CollectionViewSource处理,但是,即使我替换了“public IEnumerable TopCollection=>this.Take(10);”到“PublicObservableCollection TopCollection=>NewObservableCollection(this.Take(10));”。还是不行。是的,@mm8的改变也是必要的。尽管如此,还是要谢谢你。我已经努力了,并且成功了。然而,我需要将窗口的DataContext绑定到窗口本身,因此无法将其绑定到模型。有没有其他方法可以实现这一点?使CM成为窗口的公共属性,并将
ItemsSource
绑定到“CM.TopCollection”。也许我发现了我的问题,我应该将CM绑定到ItemsSource,但不将其设置为ItemsSource。是的,我更改了如下代码:IC.SetBinding(ItemsControl.ItemsSourceProperty,新绑定{Source=CM}); 它成功了。
<ItemsControl x:Name="IC" ItemsSource="{Binding TopCollection}" ... />