wpf 如何使用 CollectionViewSource 正确绑定(更新)DataGrid

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20188132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:06:58  来源:igfitidea点击:

How to correctly bind (update) a DataGrid with a CollectionViewSource

c#wpfdatagridobservablecollectioncollectionviewsource

提问by casaout

I have a (WPF) DataGrid where I attach an ICollectionView as

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

XAML:

XAML:

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

Constructor (Code behind)

构造函数(代码隐藏)

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

(Storage.TodoItems is an ObservableCollection)

(Storage.TodoItems 是一个 ObservableCollection)

TodoItemsCollection Property

TodoItemsCollection 属性

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

Storage.TodoItems is an ObservableCollection where a tracker adds, edits and removes items.
This changes should immediately be displayed in the DataGrid.

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

However, the problem is that all those changes are not reflected in the DataGrid(i.e. the DataGrid is not updated).
For example if I call TodoItemsCollection.Refresh(), nothing changes.
With a refresh button (only for testing purposes), I set the ItemsSource of the DataGrid to null and reset it (TodoItemsCollection = CollectionViewSource.GetDefaultView(Storage.TodoItems);).
This manual refresh displays the new/changed/removed items.
However, the filtering then doesn't work anymore.

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

I read about three dozens of blog posts and couldn't find a solution to my problems.
Usually, calling Refresh()or resetting the ItemsSourceworked well for them.

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

Any suggestionsare really much appreciated!!

任何建议都非常感谢!!

回答by blindmeis

in addition to liquidsnake786 answer - you can use the ObservableCollection instead of the ICollectionView and filtering/sorting will work just the same as long as you use CollectionViewSource.GetDefaultView(Storage.TodoItems).

除了liquidsnake786 答案-您可以使用ObservableCollection 而不是ICollectionView 并且过滤/排序的工作方式与使用CollectionViewSource.GetDefaultView(Storage.TodoItems) 时相同。

the more important thing is that the Storage.TodoItems should just initialize once otherwise TodoItemsCollection = CollectionViewSource.GetDefaultView(Storage.TodoItems); have to be called every time a new Storage.TodoItems is created. simply use clear() add() and remove() to alter your Storage.TodoItems.

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

EDIT: the usual way:

编辑:通常的方式:

-just create a OberservableCollection once (eg. within ctor). this collection will handle Add and Remove and notify the WPF ui.

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

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

-your wrapped item "TodoItem" should implement INotifyPropertyChanged to notifiy changes/edits to WPF ui

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

-create you ICollectionView once(eg. within the ctor) like you did

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

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

-alter your source collection with clear, add, remove

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

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

-be sure that your datacontext and binding is right in xaml :) btw DataContext="{Binding}" makes no sense for me.

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

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

回答by liquidsnake786

Try using ObservableCollection instead of ICollectionView and see if it helps. You should be able to call Clear() on that collection as well

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

Sorting

排序