如何防止 WPF DataGrid 在项目更新时取消选择 SelectedItem?
我的场景:我有一个后台线程,用于轮询更改并定期更新 WPF DataGrid 的 ObservableCollection(MVVM 样式)。用户可以单击 DataGrid 中的一行,然后在同一主视图上的相邻 UserControl 中显示该行的“详细信息”。
当后台线程有更新时,它会循环遍历 ObservableCollection 中的对象,并替换单个对象(如果它们已更改)(换句话说,我不会将整个新的 ObservableCollection 重新绑定到 DataGrid,而是替换集合中的单个项目;这允许 DataGrid 在更新期间保持排序顺序)。
问题是,在用户选择特定行并且详细信息显示在相邻的 UserControl 中之后,当后台线程更新 DataGrid 时,DataGrid 会丢失 SelectedItem(它会重置回索引 -1)。
如何在 ObservableCollection 更新之间保留 SelectedItem?
My scenario: I have a background thread that polls for changes and periodically updates a WPF DataGrid's ObservableCollection (MVVM-style). The user can click on a row in the DataGrid and bring up the "details" of that row in an adjacent UserControl on the same main view.
When the background thread has updates, it cycles through the objects in the ObservableCollection and replaces individual objects if they have changed (in other words, I am not rebinding a whole new ObservableCollection to the DataGrid, but instead replacing individual items in the collection; this allows the DataGrid to maintain sorting order during updates).
The problem is that after a user has selected a specific row and the details are displayed in the adjacent UserControl, when the background thread updates the DataGrid the DataGrid loses the SelectedItem (it gets reset back to index of -1).
How can I retain the SelectedItem between updates to the ObservableCollection?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您的网格是单选的,我的建议是您使用 CollectionView 作为 ItemsSource 而不是实际的 ObservableCollection。然后,确保 Datagrid.IsSynchronizedWithCurrentItem 设置为 true。最后,在“替换项目逻辑”结束时,只需将 CollectionView 的 CurrentItem 移动到相应的新项目即可。
下面的示例演示了这一点。 (不过,我在这里使用列表框。希望它能与您的数据网格配合良好)。
编辑 - 使用 MVVM 的新示例:
XAML
代码隐藏:
旧示例:
XAML:
代码隐藏:
If your grid is single-selection, my suggestion is that you use the CollectionView as the ItemsSource instead of the actual ObservableCollection. Then, make sure that Datagrid.IsSynchronizedWithCurrentItem is set to true. Finally, at the end of your "replace item logic", just move the CollectionView's CurrentItem to the corresponding new item.
Below is a sample that demonstrates this. (I'm using a ListBox here though. Hope it works fine with your Datagrid).
EDIT - NEW SAMPLE USING MVVM:
XAML
Code-Behind:
OLD SAMPLE:
XAML:
Code-behind:
我没有使用过 WPF DataGrid,但我会尝试这种方法:
向视图模型添加一个属性,该属性将保存当前所选项目的值。
使用
TwoWay
将SelectedItem
绑定到这个新属性。这样,当用户选择一行时,它将更新视图模型,并且当
ObservableCollection
更新时,它不会影响SelectedItem
绑定的属性。受到束缚,我不认为它会以你所看到的方式重置。I haven't worked with the WPF DataGrid, but I'd try this approach:
Add a property to the view-model that will hold the value of the currently selected item.
Bind
SelectedItem
to this new property usingTwoWay
.This way, when the user selects a row, it will update the view-model, and when the
ObservableCollection
gets updated it won't affect the property to whichSelectedItem
is bound. Being bound, I wouldn't expect it could reset in the way you're seeing.您可以在更新 Collection 的逻辑中,将 CollectionView.Current 项引用保存到另一个变量。然后,完成更新后,调用 CollectionView.MoveCurrentTo(variable) 来重置所选项目。
You could, in the logic that updates the Collection, save off the CollectionView.Current item reference to another variable. Then, after you're done updating, call CollectionView.MoveCurrentTo(variable) to reset the selected item.
现在可能已经解决了,但这是我所做的一个示例,它适用于购物车网格。
我有一个带有 ObservableCollection 和 CollectionView 的数据网格,由包含购物车的局部变量填充:
稍后我在函数中更改了购物车的 Valid 属性 - 不是直接更改,但重要的是 ObservableCollection 中的项目发生了更改。为了反映更改并维护选择,我只需刷新 CollectionViewSource(注意内部视图):
这样,如果购物车无效,我可以将网格中的行颜色更改为红色,但也保留我的选择。
编辑:拼写
Its probably resolved by now, but here is an example of what I did and it works for a grid of carts.
I have a datagrid with ObservableCollection and CollectionView, populated from local variable containing carts:
Later I change Valid prop of carts in a function - not directly, but important is that there is a change in item in ObservableCollection. To reflect the change and maintain selection I just refresh the CollectionViewSource (notice the inside View):
This way I am able to change the row color in grid to red if the cart is invalid, but also keep my selection.
EDIT: Spelling