ToolStripItemCollection

ToolStripItemCollection

我坚信在执行ToolStripItemCollection.AddRange时会出错:

我用两个菜单制作了Windows Forms Application,每个菜单包含2个项目。

first menu

second menu

(对不起,但是我没有足够的声誉来发布图像)。

接下来,我实现按钮单击处理程序:

private void button1_Click(object sender, EventArgs e)
{
    menu1.DropDownItems.AddRange(menu2.DropDownItems);
}


和System.ArgumentOutOfRangeException被抛出。

我很好奇为什么会发生这种情况,并用ILSpy反编译了ToolStripItemCollection程序集。这是我所看到的:

public void AddRange(ToolStripItemCollection toolStripItems)
{
    if (toolStripItems == null)
    {
        throw new ArgumentNullException("toolStripItems");
    }
    if (this.IsReadOnly)
    {
        throw new NotSupportedException(SR.GetString("ToolStripItemCollectionIsReadOnly"));
    }
    using (new LayoutTransaction(this.owner, this.owner, PropertyNames.Items))
    {
        int count = toolStripItems.Count;
        for (int i = 0; i < count; i++)
        {
            this.Add(toolStripItems[i]);
        }
    }
}


没有什么可困扰的。让我们看一下ToolStripItemCollection.Add方法:

public int Add(ToolStripItem value)
{
    this.CheckCanAddOrInsertItem(value);
    this.SetOwner(value);
    int result = base.InnerList.Add(value);
    if (this.itemsCollection && this.owner != null)
    {
        this.owner.OnItemAdded(new ToolStripItemEventArgs(value));
    }
    return result;
}


最后进入ToolStripItemCollection.SetOwner:

private void SetOwner(ToolStripItem item)
{
    if (this.itemsCollection && item != null)
    {
        if (item.Owner != null)
        {
            item.Owner.Items.Remove(item);
        }
        item.SetOwner(this.owner);
        if (item.Renderer != null)
        {
            item.Renderer.InitializeItem(item);
        }
    }
}


我们可以清楚地看到,for循环删除toolStripItems中的每个步骤。 MSDN就ToolStripItemCollection实现的IList接口发表评论:
在连续元素(例如列表)的集合中,跟随在已删除元素之后的元素将向上移动以占据腾出的位置。如果对集合进行索引,则也会更新所移动元素的索引。
结果,我们最终在错误的索引上访问了toolStripItems中的项目(第二个项目移到了位置0)。我对吗?

最佳答案

不确定100%是什么问题,但是您可以通过将集合转换为数组(需要强制转换)来解决此问题:

menu1.DropDownItems.AddRange(menu2.DropDownItems.Cast<ToolStripItem>().ToArray());


您的版本抛出错误是因为当第一个菜单添加到DropDown集合时,它正在从集合中删除,因此正在迭代,因此出现OutOfRangeException。

09-30 17:19