C# 向ListCollectionView添加项时引发异常
当我运行以下测试时,我得到ArgumentOutOfRangeException:C# 向ListCollectionView添加项时引发异常,c#,.net,wpf,exception,C#,.net,Wpf,Exception,当我运行以下测试时,我得到ArgumentOutOfRangeException: [TestClass] public class ReproduceException { [TestMethod] public void Doesnt_throw_when_adding_to_grouped_collection() { var collection = new ListCollectionView(new List<Test>());
[TestClass]
public class ReproduceException
{
[TestMethod]
public void Doesnt_throw_when_adding_to_grouped_collection()
{
var collection = new ListCollectionView(new List<Test>());
collection.SortDescriptions.Add(new SortDescription("IsTrue", ListSortDirection.Ascending));
collection.GroupDescriptions.Add(new PropertyGroupDescription("Name"));
collection.AddNewItem(new Test() { Name = "Bob", IsTrue = false });
collection.CommitNew();
}
}
public class Test
{
public string Name { get; set; }
public bool IsTrue { get; set; }
}
我可能没有正确使用
AddNewItem
/CommitNew
吗?我不确定,但我认为,您应该使用AddNew()
方法而不是AddNewItem。您将调用CommitNew()
,而不调用AddNew()
,并且没有开始事务,因此引发异常
AddNewItem()摘要:将指定的对象添加到集合。
AddNew()摘要:启动一个add事务并返回挂起的新项目。
CommitNew()摘要:结束添加事务并保存挂起的新项目。
因此,您应该编写下一行代码:
Test pendingItem = (Test)collection2.AddNew();
pendingItem.Name = "Bob";
pendingItem.IsTrue = false;
collection2.CommitNew();
可能的解决方案:
1) 在添加新项目之前执行以下操作:
collection.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning;
2) 基本上,在创建分组和排序之前尝试添加项目:
var collection = new ListCollectionView(new List<Test>());
collection.AddNewItem(new Test() { Name = "Bob", IsTrue = false });
collection.CommitNew();
collection.SortDescriptions.Add(new SortDescription("IsTrue",
ListSortDirection.Ascending));
collection.GroupDescriptions.Add(new PropertyGroupDescription("Name"));
由于您添加了GroupDescription,它将提交分组:
private void CommitNewForGrouping()
{
int num;
// !!! I believe it is None by default
switch (this.NewItemPlaceholderPosition)
{
case NewItemPlaceholderPosition.AtBeginning:
num = 1;
break;
case NewItemPlaceholderPosition.AtEnd:
num = this._group.Items.Count - 2;
break;
default:
// !!! Since you've not added groups -1 would be assigned to num
num = this._group.Items.Count - 1;
break;
}
int index = this._newItemIndex;
object item = this.EndAddNew(false);
// This method will call RemoveAt(num) where num == -1 in your case
this._group.RemoveSpecialItem(num, item, false);
this.ProcessCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,
item, index));
}
internal void RemoveSpecialItem(int index, object item, bool loading)
{
...
// will fail since index always -1
base.ProtectedItems.RemoveAt(index);
...
}
LCV有私有方法
ProcessCollectionChangedWithAdjustedIndex
,该方法在不同的场景中调整索引,但在添加具有分组功能的新项时未调用该方法,我不确定为什么看起来这是出于设计(?)因此,您必须在新项目开始时手动指定占位符。我刚刚尝试过,但不幸的是,它引发了相同的异常2)我可以确认在添加项目后添加排序和组是否有效,但不幸的是,我需要能够在设置集合视图后添加新项目,而不是继续添加/删除排序和分组:)解决方案1)有效!非常感谢。您认为这是预期的行为还是一个bug?
// !!! When you've added GroupDescription this.IsGrouping becomes true!
if (this.IsGrouping)
{
this.CommitNewForGrouping();
}
private void CommitNewForGrouping()
{
int num;
// !!! I believe it is None by default
switch (this.NewItemPlaceholderPosition)
{
case NewItemPlaceholderPosition.AtBeginning:
num = 1;
break;
case NewItemPlaceholderPosition.AtEnd:
num = this._group.Items.Count - 2;
break;
default:
// !!! Since you've not added groups -1 would be assigned to num
num = this._group.Items.Count - 1;
break;
}
int index = this._newItemIndex;
object item = this.EndAddNew(false);
// This method will call RemoveAt(num) where num == -1 in your case
this._group.RemoveSpecialItem(num, item, false);
this.ProcessCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,
item, index));
}
internal void RemoveSpecialItem(int index, object item, bool loading)
{
...
// will fail since index always -1
base.ProtectedItems.RemoveAt(index);
...
}