簡體   English   中英

將項目添加到ListCollectionView時引發異常

[英]Exception being thrown when adding an item to a ListCollectionView

當我運行以下測試時,我收到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嗎?

可能的解決方案:

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 (?!),所以您已手動指定了占位符AtBeginning新項目。

我不確定,但是我認為您應該使用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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM