在 ViewModel 中修改 ObservableCollection 时绑定到 ObservableCollection 的 DataGrid MultiSelect 不稳定
DataGrid MultiSelect bound to ObservableCollection unstable when ObservableCollection is modified in the ViewModel
我正在构建一个 WPF C# 应用程序,其中有多个 DataGrids
绑定到各自包含对象的 ObservableCollections
。
为了简单起见,我将重点介绍绑定到 Conduits
ObservableCollection
的 DataGrid
。
DataGrids
设置为多selectSelectionMode="Extended"
。
DataGrids
中的数据也通过 Canvas
和绘图元素在二维视图中表示。
想法是用户可以 select 二维对象或 DataGrids
,作为单个项目,或多个 items/rows,以及 DataGrid
行,或 2D 中的对象将突出显示。
这会产生一些不稳定的结果。太多无法列出,所以我将专注于删除项目。当 DataGrid
ViewModels
尚未初始化时,我可以毫无问题地删除 2D 中的对象。初始化后,在 2D 中删除时出现以下错误。
`System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'`
二维删除对象如下:
foreach (object _conduit in SelectedConduitList)
{
if (_conduit is Conduit conduit)
{
Conduits.Remove(conduit);
}
}
关联的 DataGrid
绑定到对象,selected 对象如下:
<custom:ConduitDataGrid
ItemsSource="{Binding Path=NetworkMain.Conduits}"
SelectionMode="Extended"
SelectedItemsList="{Binding NetworkMain.SelectedConduitList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
这是导管 DataGrids
的 ObservableCollection
和 selected 导管
的列表
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));
}
}
为了让 DataGrids
将多个 selected 行绑定到 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
}
有谁知道为什么我不能在我的 2D 布局 ViewModel
中修改(例如删除)SelectedConduitList
中的一个对象,而一旦 DataGrid ViewModels
有初始化了吗?
异常消息意味着您无法在使用 foreach
循环枚举时从 IEnumerable
中删除项目。
一般的解决方案是将foreach
循环替换为for
循环并向后遍历集合:
for (int i = SelectedConduitList.Count - 1; i >= 0; i--)
{
Conduit conduit = SelectedConduitList[i] as Conduit;
if (conduit != null)
Conduits.Remove(conduit);
}
更多信息请参考this博客post。
I can delete objects in the 2D without problem when the DataGrid ViewModels have not been initialized. Once they are initialized I get the following error when deleting in 2D.
从源附加到的集合中删除会导致从选定元素的集合中删除,您在该集合上有一个 foreach 循环。
不允许在 运行 时更改 foreach 源。
这是一个常见问题,最简单的解决方案是复制列表,然后对其进行循环。
foreach (Conduit conduit in SelectedConduitList.OfType<Conduit>().ToList())
{
Conduits.Remove(conduit);
}
我正在构建一个 WPF C# 应用程序,其中有多个 DataGrids
绑定到各自包含对象的 ObservableCollections
。
为了简单起见,我将重点介绍绑定到 Conduits
ObservableCollection
的 DataGrid
。
DataGrids
设置为多selectSelectionMode="Extended"
。
DataGrids
中的数据也通过 Canvas
和绘图元素在二维视图中表示。
想法是用户可以 select 二维对象或 DataGrids
,作为单个项目,或多个 items/rows,以及 DataGrid
行,或 2D 中的对象将突出显示。
这会产生一些不稳定的结果。太多无法列出,所以我将专注于删除项目。当 DataGrid
ViewModels
尚未初始化时,我可以毫无问题地删除 2D 中的对象。初始化后,在 2D 中删除时出现以下错误。
`System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'`
二维删除对象如下:
foreach (object _conduit in SelectedConduitList)
{
if (_conduit is Conduit conduit)
{
Conduits.Remove(conduit);
}
}
关联的 DataGrid
绑定到对象,selected 对象如下:
<custom:ConduitDataGrid
ItemsSource="{Binding Path=NetworkMain.Conduits}"
SelectionMode="Extended"
SelectedItemsList="{Binding NetworkMain.SelectedConduitList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
这是导管 DataGrids
的 ObservableCollection
和 selected 导管
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));
}
}
为了让 DataGrids
将多个 selected 行绑定到 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
}
有谁知道为什么我不能在我的 2D 布局 ViewModel
中修改(例如删除)SelectedConduitList
中的一个对象,而一旦 DataGrid ViewModels
有初始化了吗?
异常消息意味着您无法在使用 foreach
循环枚举时从 IEnumerable
中删除项目。
一般的解决方案是将foreach
循环替换为for
循环并向后遍历集合:
for (int i = SelectedConduitList.Count - 1; i >= 0; i--)
{
Conduit conduit = SelectedConduitList[i] as Conduit;
if (conduit != null)
Conduits.Remove(conduit);
}
更多信息请参考this博客post。
I can delete objects in the 2D without problem when the DataGrid ViewModels have not been initialized. Once they are initialized I get the following error when deleting in 2D.
从源附加到的集合中删除会导致从选定元素的集合中删除,您在该集合上有一个 foreach 循环。
不允许在 运行 时更改 foreach 源。
这是一个常见问题,最简单的解决方案是复制列表,然后对其进行循环。
foreach (Conduit conduit in SelectedConduitList.OfType<Conduit>().ToList())
{
Conduits.Remove(conduit);
}