-5

我随机收到以下异常。工具条菜单是动态创建的。

System.ArgumentOutOfRangeException - Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.ArrayList.get_Item(Int32 index)
at System.Windows.Forms.Layout.ArrangedElementCollection.get_Item(Int32 index)
at System.Windows.Forms.Layout.FlowLayout.xLayoutRow(ContainerProxy containerProxy, ElementProxy elementProxy, Int32 startIndex, Int32 endIndex, Rectangle rowBounds, Int32& breakIndex, Boolean measureOnly)
at System.Windows.Forms.Layout.FlowLayout.xLayout(IArrangedElement container, Rectangle displayRect, Boolean measureOnly)
at System.Windows.Forms.Layout.FlowLayout.GetPreferredSize(IArrangedElement container, Size proposedConstraints)
at System.Windows.Forms.ToolStripDropDownMenu.ToolStripDropDownLayoutEngine.GetPreferredSize(IArrangedElement container, Size proposedConstraints)
at System.Windows.Forms.ToolStrip.GetPreferredSizeCore(Size proposedSize)
at System.Windows.Forms.Control.GetPreferredSize(Size proposedSize)
at System.Windows.Forms.ToolStripDropDown.GetSuggestedSize()
at System.Windows.Forms.ToolStripDropDown.AdjustSize()
at System.Windows.Forms.ToolStripDropDownMenu.OnLayout(LayoutEventArgs e)
at System.Windows.Forms.Control.PerformLayout(LayoutEventArgs args)
at System.Windows.Forms.Control.System.Windows.Forms.Layout.IArrangedElement.PerformLayout(IArrangedElement affectedElement, String affectedProperty)
at System.Windows.Forms.ToolStripItem.InvalidateItemLayout(String affectedProperty, Boolean invalidatePainting)
at System.Windows.Forms.ToolStripDropDownItem.OnRightToLeftChanged(EventArgs e)
at System.Windows.Forms.ToolStripItem.OnOwnerChanged(EventArgs e)
at System.Windows.Forms.ToolStripMenuItem.OnOwnerChanged(EventArgs e)
at System.Windows.Forms.ToolStripItem.SetOwner(ToolStrip newOwner)
at System.Windows.Forms.ToolStripItemCollection.SetOwner(ToolStripItem item)
at System.Windows.Forms.ToolStripItemCollection.Add(ToolStripItem value)

异常发生在以下方法中。将项目添加到 mnuRoot 时会发生这种情况。在右键单击选定项目时调用此方法。

private static void BuildMenu(ToolStripMenuItem root, XMLSerItem mnuItem, ToolStrip mnuRoot, Dictionary<string, Image> dctIcons, CustomMenuClickHandler dlgEventHandler, ToolStripMenuItem mnuAddAfter, bool bHideDisabled)
        {
            if(root == null)
            {
                // Try to find an existing menu item
                ToolStripItem mnuMerge = FindMenuItem( mnuRoot.Items, mnuItem );
                if(mnuMerge == null)
                {
                    lock( mnuRoot.Items )
                    {
                            if (mnuAddAfter == null)
                            {             
                                mnuRoot.Items.Add(item);
                            }
                            else
                            {
                                mnuRoot.Items.Insert(mnuRoot.Items.IndexOf(mnuAddAfter), item);
                            }

                    }
                }
                else
                {
                    // Use a reference to the found item
                    item = mnuMerge;
                }
            }
            else
            {
                // Try to find an existing menu item
                ToolStripItem mnuMerge = FindMenuItem( root.DropDownItems, mnuItem );
                if(mnuMerge == null)
                {
                    lock( root.DropDownItems )
                    {
                        // Add the menu item to the root item
                        root.DropDownItems.Add( item );
                    }
                }
                else
                {

                    item = mnuMerge;
                }
            }         
        }
}
4

2 回答 2

0

参数超出范围的异常文本说明如下:

指数超出范围。必须是非负数且小于集合的大小。

你声称这个异常发生在这一行:

mnuRoot.Items.Insert(mnuRoot.Items.IndexOf(mnuAddAfter), item);

从堆栈跟踪中,我们了解到异常是在ItemArraylist 的访问器处引发的。这意味着我们在 Insert 方法中提供的第一个参数必须是负数或大于 Arraylist 的大小。让我们首先分析我们的索引值是否很大。

该索引是从 拥有的项目的集合中获得的,mnuRoot并且也在Insert的同一集合中mnuRoot。值太大是非常不可能的,因为代码引用的是同一个集合。唯一可能出错的情况是,如果多个线程正在更新该 Arraylist 并通过判断lock您试图防止这种情况的语句。

保留负数作为选项。如果对 的引用mnuAddAfter不在 的集合中,则会出现mnuRoot.Items。由于您已经在检查 null 我认为这是可能发生的情况。

根据提供的代码片段,我假设您想添加itemmnuRoot.Items集合中,无论需要什么

如果您搜索空值,则IndexOf执行ArrayList不会中断,如果在列表中找不到1则该方法返回 -1。使用这些知识,以下实现将防止参数超出范围异常。

var index = mnuRoot.Items.IndexOf(mnuAddAfter); // if mnuAddAfter is null -1 is returned
if (index == -1)
{             
   mnuRoot.Items.Add(item);
}
else
{
    mnuRoot.Items.Insert(index, item);
}

1. 对于挑剔者:ToolStripItemCollection保证不会在其集合中插入空值

于 2014-01-18T11:31:24.080 回答
0

尽管出于充分的理由,这个问题被否决了,但这是我在谷歌搜索“xLayoutRow ArgumentOutOfRangeException”时得到的唯一命中,所以我仍然会在这里分享我的经验。

我在这篇文章中遇到了堆栈跟踪顶部的异常:

System.ArgumentOutOfRangeException - Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.ArrayList.get_Item(Int32 index)
at System.Windows.Forms.Layout.ArrangedElementCollection.get_Item(Int32 index)
at System.Windows.Forms.Layout.FlowLayout.xLayoutRow(ContainerProxy containerProxy, ElementProxy elementProxy, Int32 startIndex, Int32 endIndex, Rectangle rowBounds, Int32& breakIndex, Boolean measureOnly)
at System.Windows.Forms.Layout.FlowLayout.xLayout(IArrangedElement container, Rectangle displayRect, Boolean measureOnly)
at System.Windows.Forms.Layout.FlowLayout.GetPreferredSize(IArrangedElement container, Size proposedConstraints)

就我而言,原因总结如下:

  • MyControl 类型的 UserControl 包含一个FlowLayoutPanel.
  • a的实例MyControl被实例化并添加到Controls容器控件的集合中bb.Controls.Add(a)
  • 这个Add操作过程中,通过触发其他事件的事件,将里面的所有控件b.Controls都释放掉,包括a.
  • 异常来自b.Controls.Add(a)尚未完成的调用。

当然,在将控件添加到控件集合时处理控件不是我的意图,找到原因可以让我立即解决问题。似乎发生的事情是FlowLayoutPanel尝试进行布局,但它及其控件正在被删除并在飞行中处置,这可以理解使其失败。

也许这有助于 OP 或遇到此异常的其他人。

于 2014-02-24T16:05:51.683 回答