当我运行以下测试时,我得到一个ArgumentOutOfRangeException:
[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; }
}
我得到以下异常:
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.ObjectModel.Collection`1.RemoveAt(Int32 index)
at System.Windows.Data.ListCollectionView.CommitNewForGrouping()
at System.Windows.Data.ListCollectionView.CommitNew()
我可能没有以正确的方式使用AddNewItem
/ CommitNew
吗?
答案 0 :(得分:1)
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"));
在深入研究.NET Reflector后,CommitNew()
方法有以下检查:
// !!! When you've added GroupDescription this.IsGrouping becomes true!
if (this.IsGrouping)
{
this.CommitNewForGrouping();
}
由于您已添加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
,它可以在不同情况下调整索引,但是在添加分组启用的新项目时不调用它,我不知道为什么这样看起来像是设计(?!)所以您已为新项目手动指定占位符AtBeginning
。
答案 1 :(得分:0)
我不确定,但我认为你应该使用AddNew()
方法而不是AddNewItem。你打算调用CommitNew()
,而不是调用AddNew()
,并且没有开始事务,所以抛出了异常。
AddNewItem()摘要:Adds the specified object to the collection.
AddNew()摘要:Starts an add transaction and returns the pending new item.
CommitNew()摘要:Ends the add transaction and saves the pending new item.
所以,你应该编写下一行代码:
Test pendingItem = (Test)collection2.AddNew();
pendingItem.Name = "Bob";
pendingItem.IsTrue = false;
collection2.CommitNew();