System.ArgumentOutOfRangeException工具栏菜单

本文关键字:菜单 工具栏 ArgumentOutOfRangeException System | 更新日期: 2024-09-24 16:56:17

我随机得到以下异常。toolstrip菜单是动态创建的。

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;
                }
            }         
        }
}

System.ArgumentOutOfRangeException工具栏菜单

尽管这个问题被否决是有充分理由的,但这是我在谷歌上搜索"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
  • MyControl的实例a被实例化并添加到容器控件b:b.Controls.Add(a)Controls集合
  • Add操作期间,通过触发其他事件的事件,将处理b.Controls中的所有控件,包括a
  • 调用b.Controls.Add(a)之后出现异常,该调用仍未完成

当然,在将控件添加到控件集合的同时处理控件并不是我的本意,找到原因使我能够立即解决问题。似乎发生的是,FlowLayoutPanel试图进行布局,但它和它的控制装置在飞行中被拆除和处理,这可以理解地使它失败了。

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

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

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

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

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

从堆栈跟踪中,我们了解到异常是在Arraylist的Item访问器处引发的。这意味着我们在Insert方法中提供的第一个参数必须是负数或大于Arraylist的大小。如果我们的指数值太大,让我们先进行anaylize。

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

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

根据提供的代码片段,我假设您希望将item添加到mnuRoot.Items集合,无论需要什么

如果搜索空值,ArrayListIndexOf实现不会中断,如果在列表中找不到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.对于nitpickers:ToolStripItemCollection保证在其集合中不插入空值