[英]DataGrid MultiSelect bound to ObservableCollection unstable when ObservableCollection is modified in the ViewModel
I'm building a WPF C# application that has multiple DataGrids
bound to their respective ObservableCollections
that contain objects.我正在构建一个 WPF C# 应用程序,该应用程序有多个
DataGrids
绑定到它们各自包含对象的ObservableCollections
。
I will focus on the DataGrid
that binds to the Conduits
ObservableCollection
to keep things simple.我将专注于绑定到
Conduits
ObservableCollection
的DataGrid
以保持简单。
The DataGrids
are set to multi select SelectionMode="Extended"
. DataGrids
设置为多 select SelectionMode="Extended"
。 The data in the DataGrids
is also represented in a 2D view via a Canvas
and drawing elements. DataGrids
中的数据也通过Canvas
和绘图元素在 2D 视图中表示。
The idea is the user can select the objects in 2D or the DataGrids
, as a single item, or multiple items/rows, and the DataGrid
row, or object in 2D will be highlighted.这个想法是用户可以 select 2D 或
DataGrids
中的对象,作为单个项目,或多个项目/行,并且DataGrid
行或 object 在 2D 将突出显示。
This is producing some unstable results.这会产生一些不稳定的结果。 Too many to list, so I will focus on deleting items.
太多无法列出,所以我将专注于删除项目。 I can delete objects in the 2D without problem when the
DataGrid
ViewModels
have not been initialized.当
DataGrid
ViewModels
尚未初始化时,我可以毫无问题地删除 2D 中的对象。 Once they are initialized I get the following error when deleting in 2D.初始化它们后,在 2D 中删除时会出现以下错误。
`System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'`
Objects are deleted in 2D as follows:对象在 2D 中被删除,如下所示:
foreach (object _conduit in SelectedConduitList)
{
if (_conduit is Conduit conduit)
{
Conduits.Remove(conduit);
}
}
The associated DataGrid
is bound to the objects, and selected objects as follows:关联的
DataGrid
绑定到对象,选中对象如下:
<custom:ConduitDataGrid
ItemsSource="{Binding Path=NetworkMain.Conduits}"
SelectionMode="Extended"
SelectedItemsList="{Binding NetworkMain.SelectedConduitList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
Here is the ObservableCollection
for the Conduit DataGrids
and the list for the selected Conduits这是 Conduit
DataGrids
的ObservableCollection
和所选 Conduit 的列表
public ObservableCollection<Conduit> Conduits { get; set; } = new();
private IList _selectedConduitList = new ArrayList();
public IList SelectedConduitList
{
get { return _selectedConduitList; }
set
{
_selectedConduitList = value;
//changes the IsSelected property of all objects in the ObserbservableCollection to false
DeselectAll();
//changes the IsSelected property of all objects in the ObserbservableCollection to true if the object exists in the SelectedConduitList
SelectConduits();
NotifyOfPropertyChange(nameof(SelectedConduitList));
}
}
In order to get the DataGrids
to bind multiple selected rows to the SelectedConduitList
a custom datagrid
was used as follows:为了让
DataGrids
将多个选定的行绑定到SelectedConduitList
,使用了自定义datagrid
,如下所示:
public class ConduitDataGrid : DataGrid
{
public ConduitDataGrid()
{
this.SelectionChanged += CustomDataGrid_SelectionChanged;
}
void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.SelectedItemsList = this.SelectedItems;
}
#region SelectedItemsList
public IList SelectedItemsList
{
get { return (IList)GetValue(SelectedItemsListProperty); }
set
{
SetValue(SelectedItemsListProperty, value);
}
}
public static readonly DependencyProperty SelectedItemsListProperty =
DependencyProperty.Register(nameof(SelectedItemsList), typeof(IList), typeof(ConduitDataGrid), new PropertyMetadata(null));
#endregion
}
Does anybody know why I can't modify (for example delete) an object form the SelectedConduitList
from within my 2D Layout ViewModel
without throwing an error once the DataGrid ViewModels
have been initialised?有谁知道为什么我不能从我的 2D 布局
ViewModel
中修改(例如删除)一个 object 形式的SelectedConduitList
而不会在初始化DataGrid ViewModels
后引发错误?
The exception message means that you cannot remove an item from an IEnumerable
while enumerating it using a foreach
loop.异常消息意味着您无法在使用
foreach
循环枚举IEnumerable
时将其删除。
The general solution is to replace the foreach
loop with a for
loop and iterate through the collection backwards:一般的解决方案是用
for
循环替换foreach
循环并向后迭代集合:
for (int i = SelectedConduitList.Count - 1; i >= 0; i--)
{
Conduit conduit = SelectedConduitList[i] as Conduit;
if (conduit != null)
Conduits.Remove(conduit);
}
Please refer to this blog post for more information.请参阅此博客文章了解更多信息。
I can delete objects in the 2D without problem when the DataGrid ViewModels have not been initialized.
当 DataGrid ViewModel 尚未初始化时,我可以毫无问题地删除 2D 中的对象。 Once they are initialized I get the following error when deleting in 2D.
初始化它们后,在 2D 中删除时会出现以下错误。
Deleting from the collection to which the source is attached leads to the deletion from the collection of selected elements, on which you have a foreach loop.从附加源的集合中删除会导致从选定元素的集合中删除,在该集合上您有一个 foreach 循环。 Changing the foreach source while it is running is not allowed.
不允许在运行时更改 foreach 源。
This is a common problem and the simplest solution is to make a copy of the list and then loop over it.这是一个常见问题,最简单的解决方案是制作列表的副本,然后循环遍历它。
foreach (Conduit conduit in SelectedConduitList.OfType<Conduit>().ToList())
{
Conduits.Remove(conduit);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.