You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ListView添加项报错:无法在多个位置添加/插入同一项

问题描述

向ListView添加项时抛出异常:Cannot add or insert the item '0' in more than one place,预期能正常添加项,实际无法完成添加。

相关代码

Takenshows.cs 类定义

namespace MainLayer
{
public partial class Takenshows : Form
{
    int c;
    int f;
    int d = 0;

    public List<Show> myShows;
    private ListViewColumnSorter lvwColumnSorter;
    Main p;

构造函数

public Takenshows()
    {
        InitializeComponent();
        lvwColumnSorter = new ListViewColumnSorter();
        this.listView1.ListViewItemSorter = lvwColumnSorter;
        myShows = new List<Show>();
    }

    public Takenshows(IEnumerable<Show> shows) : this()
    {
        AddShows(shows);
    }

添加Show项到ListView的方法

internal void AddShow(Show item) => AddShows(new[] { item });

internal void AddShows(IEnumerable<Show> items)
{
    var lvis = items.Select(x => new ListViewItem(new[]
    {
        x.OrdNum.ToString(),
        x.DTshow.ToString(),
        x.values.ToString(),
        x.practiseNumber.ToString()
    }));

    listView1.Items.AddRange(lvis.ToArray());
}

清空ListView方法

internal void emptyShows()
{
    listView1.Items.Clear();
}

获取Show项方法

public List<Show> getShows(List<Show> items)
{
    return items;
}

异常发生的Takenshows_Load方法

private void Takenshows_Load(object sender, EventArgs e)
{
    // 设置视图模式以显示列
    listView1.View = View.Details;

    listView1.Columns.Add("Order Number", 115, HorizontalAlignment.Left);
    listView1.Columns.Add("Practise datetime", 140, HorizontalAlignment.Left);
    listView1.Columns.Add("values", 420, HorizontalAlignment.Left);
    listView1.Columns.Add("Practise number", 105, HorizontalAlignment.Left);

    foreach (ListViewItem item in listView1.Items)
    {
        int index = listView1.Items.IndexOf(item);
        item.Tag = index;
        item.Text = index.ToString();
        item.SubItems.Add(listView1.Items[index].SubItems[0].Text);
        item.SubItems.Add(listView1.Items[index].SubItems[1].Text);
        item.SubItems.Add(listView1.Items[index].SubItems[2].Text);
        item.SubItems.Add(listView1.Items[index].SubItems[3].Text);
        listView1.Items.Add(item); // 此处抛出异常:cannot add the item '0' in more than one place
    }
    myShows = listView1.SelectedItems.Cast<ListViewItem>().Select(lvi => (Show)lvi.Tag).ToList();

    for (int j = 0; j < listView1.Items.Count; j++)
    {
        c = c + 1;
        listView1.Items[j].SubItems[0].Text = c.ToString();
    }

    f = Int32.Parse(c.ToString());

    var frm3 = Application.OpenForms.OfType<Principal>().First();

    if (frm3 != null)
    {
        frm3.devCont();
        frm3.devcontlist(f);
        frm3.devMed(myShows);
    }
}

ListView选中项变更事件

private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
    listView1.BeginUpdate();
    listView1.EndUpdate();
    listView1.Invalidate();
    listView1.Update();
}

删除项按钮事件

private void button1_Click(object sender, EventArgs e)
{
    c = 0;

    if (listView1.SelectedItems != null)
    {
        for (int i = 0; i < listView1.Items.Count; i++)
        {
            if (listView1.Items[i].Selected)
            {
                DialogResult dr = MessageBox.Show("Are you sure you want to remove the selected item?", "WARNING", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);

                switch (dr)
                {
                    case DialogResult.Yes:
                        listView1.Items[i].Remove();
                        i--;

                        for (int j = 0; j < listView1.Items.Count; j++)
                        {
                            c = c + 1;
                            listView1.Items[j].SubItems[0].Text = c.ToString();
                        }

                        f = Int32.Parse(c.ToString());
                        myShows = listView1.SelectedItems.Cast<ListViewItem>().Select(lvi => (Show)lvi.Tag).ToList();

                        var frm2 = Application.OpenForms.OfType<Principal>().First();
                        if (frm2 != null)
                        {
                            frm2.devCont();
                            frm2.devcontlist(f);
                            frm2.devMed(myShows);
                        }
                        break;
                    case DialogResult.No:
                        break;
                }
            }
        }
    }
}

ListView列排序事件

private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
{
    if (e.Column == 0)
    {
        if (lvwColumnSorter.SortColumn == 0)
        {
            lvwColumnSorter.SortColumn = e.Column;
            lvwColumnSorter.Order = SortOrder.Ascending;
        }
    }
    this.listView1.Sort();
}
  }
}

Main.cs 添加项按钮事件

private void button2_Click(object sender, EventArgs e)
{
    string values = textBox_F.Text + " " + textBox_PT.Text + " " + textBox_QT.Text + " "
        + textBox_ST.Text + " " + textBox_FPT.Text;

    c = c + 1;

    watchedShow = new Show
    {
        OrdNum = c + d,
        DTShow = DateTime.Now,
        Values = values,
        practiseNumber = GetPractiseNumberLN.getInstance().getPractiseNum()
    };
    watchedShows.Add(watchedShow);

    var frm = Application.OpenForms.OfType<Takenshows>().FirstOrDefault();
    if (frm == null)
    {
        frm = new Takenshows(watchedShows);
        frm.Show();
    }
    else
    {
        frm.AddShow(watchedShow);
        frm.Activate();
    }
}

异常出现在Takenshows_Load方法的listView1.Items.Add(item);行,尝试过将foreach替换为for循环,问题依旧。请问如何解决该异常,实现正常添加ListView项?


解决方案

问题根源

Takenshows_Load里的foreach循环犯了两个核心错误:

  1. 重复添加已有项:你遍历的是listView1.Items里的现有项,然后直接调用Add(item)试图把同一个ListViewItem实例再次加入列表。而一个ListViewItem实例只能属于一个ListView,这直接触发了异常。
  2. 错误的子项操作:循环里给已有项重复添加子项,但这些子项在AddShows创建ListViewItem时就已经初始化完成了,这种操作不仅多余,还会导致子项重复,逻辑完全混乱。
    另外,myShows的赋值逻辑也错了:你试图从选中项转换Tag,但此时根本没有选中项,而且Tag被错误赋值为索引,而非Show对象。

修改步骤

1. 删除错误的foreach循环

直接删掉Takenshows_Load里的整个foreach循环块,因为AddShows已经正确把ListViewItem添加到了ListView中,不需要重复处理。

2. 修正AddShows方法,绑定Show对象到Tag

在创建ListViewItem时,把对应的Show对象绑定到Tag,方便后续获取:

internal void AddShows(IEnumerable<Show> items)
{
    var lvis = items.Select(x => 
    {
        var lvi = new ListViewItem(new[]
        {
            x.OrdNum.ToString(),
            x.DTshow.ToString(),
            x.values.ToString(),
            x.practiseNumber.ToString()
        });
        lvi.Tag = x; // 将Show对象绑定到Tag属性
        return lvi;
    });

    listView1.Items.AddRange(lvis.ToArray());
}

3. 修正Takenshows_Load中的myShows赋值

改为从所有项的Tag中获取Show对象:

// 替换原来的myShows赋值行
myShows = listView1.Items.Cast<ListViewItem>().Select(lvi => (Show)lvi.Tag).ToList();

4. 修正序号更新的初始值

确保序号从1开始,初始化c为0:

c = 0; // 初始化c为0
for (int j = 0; j < listView1.Items.Count; j++)
{
    c = c + 1;
    listView1.Items[j].SubItems[0].Text = c.ToString();
}

5. 修正删除按钮中的myShows更新

删除后应该获取所有项的Show对象,而非仅选中项:

// 替换原来的myShows赋值行
myShows = listView1.Items.Cast<ListViewItem>().Select(lvi => (Show)lvi.Tag).ToList();

修改后的Takenshows_Load方法

private void Takenshows_Load(object sender, EventArgs e)
{
    // 设置视图模式
    listView1.View = View.Details;

    // 添加列
    listView1.Columns.Add("Order Number", 115, HorizontalAlignment.Left);
    listView1.Columns.Add("Practise datetime", 140, HorizontalAlignment.Left);
    listView1.Columns.Add("values", 420, HorizontalAlignment.Left);
    listView1.Columns.Add("Practise number", 105, HorizontalAlignment.Left);

    // 获取所有Show对象
    myShows = listView1.Items.Cast<ListViewItem>().Select(lvi => (Show)lvi.Tag).ToList();

    // 更新序号
    c = 0;
    for (int j = 0; j < listView1.Items.Count; j++)
    {
        c = c + 1;
        listView1.Items[j].SubItems[0].Text = c.ToString();
    }

    f = c; // 直接使用c的值,无需转字符串再解析

    var frm3 = Application.OpenForms.OfType<Principal>().FirstOrDefault();
    if (frm3 != null)
    {
        frm3.devCont();
        frm3.devcontlist(f);
        frm3.devMed(myShows);
    }
}

额外优化建议

  • getShows方法只是返回传入的参数,完全没有作用,可以直接删除。
  • listView1_SelectedIndexChanged事件里的BeginUpdate和EndUpdate没有实际操作列表内容,可简化或删除。
  • 把序号更新逻辑封装成单独方法,避免加载和删除时重复写相同代码。

内容的提问来源于stack exchange,提问作者Francisco J A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:50:46