【问题标题】:How to correctly bind (update) a DataGrid with a CollectionViewSource如何正确绑定(更新)具有 CollectionViewSource 的 DataGrid
【发布时间】:2013-12-09 21:18:01
【问题描述】:

我有一个 (WPF) DataGrid,我在其中附加了一个 ICollectionView

XAML:

 <DataGrid x:Name="TodoList" ItemsSource="{Binding TodoItemsCollection}" DataContext="{Binding}" />

构造函数(代码隐藏)

 TodoItemsCollection = CollectionViewSource.GetDefaultView(Storage.TodoItems);
 TodoItemsCollection.Filter = TodoItemsFilter;

(Storage.TodoItems 是一个 ObservableCollection)

TodoItemsCollection 属性

 private ICollectionView _todoItemsCollection;
 public ICollectionView TodoItemsCollection
 {
     get { return _todoItemsCollection; }
     set 
     {
         if (_todoItemsCollection != value)
         {
             _todoItemsCollection = value;
             OnPropertyChanged("TodoItemsCollection");
         }
     }
 }

Storage.TodoItems 是一个 ObservableCollection,跟踪器在其中添加、编辑和删除项目
此更改应立即显示在 DataGrid 中。

但是,问题在于所有这些更改都没有反映在 DataGrid 中(即 DataGrid 没有更新)。
例如,如果我打电话给TodoItemsCollection.Refresh(),没有任何变化。
使用刷新按钮(仅用于测试目的),我将 DataGrid 的 ItemsSource 设置为 null 并将其重置 (TodoItemsCollection = CollectionViewSource.GetDefaultView(Storage.TodoItems);)。
此手动刷新显示新的/更改的/删除的项目。
但是,过滤不再起作用

我阅读了大约三几十篇博客文章,但找不到解决问题的方法。
通常,调用Refresh() 或重置ItemsSource 对他们来说效果很好。

非常感谢任何建议

【问题讨论】:

  • 避免将绑定集合设置为空,而是使用 Clear()。至于你的问题,你可以试试 OnPropertyChanged(() => TodoItemsCollection);
  • 对不起,我真的不明白你的意思。我将 TodoList.ItemsSource 设置为空。而且我不能在 TodoItemsCollection 上调用 Clear()。我该怎么办?谢谢!
  • 我不能在 OnPropertyChanged() 中使用 LambdaFunction。您如何建议 OnPropertyChanged() 方法应该是什么样子?谢谢。
  • 对我来说,解决方案是在后面的代码中重新分配 ItemsSourceTodoList.ItemsSource = TodoItemsCollection;

标签: c# wpf datagrid observablecollection collectionviewsource


【解决方案1】:

除了liquidsnake786 答案 - 您可以使用 ObservableCollection 而不是 ICollectionView 并且过滤/排序将与您使用 CollectionViewSource.GetDefaultView(Storage.TodoItems) 一样。

更重要的是 Storage.TodoItems 应该只初始化一次,否则 TodoItemsCollection = CollectionViewSource.GetDefaultView(Storage.TodoItems);每次创建新的 Storage.TodoItems 时都必须调用它。只需使用 clear() add() 和 remove() 来更改您的 Storage.TodoItems。

编辑:通常的方式:

-只需创建一次 OberservableCollection(例如在 ctor 中)。此集合将处理 Add 和 Remove 并通知 WPF ui。

this.MyCollection = new OberservableCollection<TodoItem>();

-您的包装项目“TodoItem”应该实现 INotifyPropertyChanged 以通知 WPF ui 的更改/编辑

-像你一样创建一次 ICollectionView(例如在 ctor 中)

 this.MyView = CollectionViewSource.GetDefaultView(MyCollection);
 this.MyView.Filter = TodoItemsFilter;

-通过清除、添加、删除来更改您的源集合

 this.MyCollection.Clear();
 foreach(var item in MyNewCollectionFromAnywhere)
 { this.MyCollection.Add(item);}
 this.MyView.Refresh();

-确保您的数据上下文和绑定在 xaml 中是正确的 :) btw DataContext="{Binding}" 对我来说毫无意义。

<DataGrid ItemsSource="{Binding MyView}"/>

【讨论】:

  • 感谢您的回答。我不是已经通过写TodoItemsCollection = CollectionViewSource.GetDefaultView(Storage.TodoItems); 来做到这一点了吗? TodoItems 是一个 ObservableCollection,其中项目被添加/修改/删除。但是我不能在这个列表上运行 clear(),因为我不想改变它。基本上,DataGrid 应该只显示整个 ObservableCollection,但允许用户过滤它(使用单独的字段)。您能否告诉我如何更改代码以使其正常工作?非常感谢!
  • 很遗憾没有。但它确实帮助了我,因为我可以提高我对 CollectionViewSources-Stuff 的理解。此外,过滤器现在在用户手动刷新后仍然有效。但是,我真的希望找到一个不必依赖刷新按钮的解决方案。谢谢!
【解决方案2】:

尝试使用 ObservableCollection 而不是 ICollectionView 看看是否有帮助。您应该也可以在该集合上调用 Clear()

【讨论】:

  • 只需将 ObservableCollection 绑定到 DataGrid 即可。但我想在上面运行 fiters,这就是我使用 ICollectionView 的原因。还是我误解了你的答案?谢谢。
  • 看这张图,也许它会帮助你理解我想说什么...blogs.msdn.com/blogfiles/luc/WindowsLiveWriter/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 2021-07-10
  • 1970-01-01
  • 2011-01-13
  • 2021-08-31
  • 2017-04-22
  • 1970-01-01
相关资源
最近更新 更多