【问题标题】:listbox error: Items collection cannot be modified when the DataSource property is set列表框错误:设置 DataSource 属性时无法修改项目集合
【发布时间】:2014-10-19 19:45:18
【问题描述】:

我在一个窗口形式中有 2 个列表框,一个在左侧,一个在右侧。这 第一个列表框有一些项目,而第二个列表框是空的。也有 是用于将项目移出/移出的 2 个列表框之间的 2 个按钮 第一个和第二个列表框

我的问题是,在我将数据绑定到第一个列表框后(从 一个数据库,使用 DisplayMember 和 ValueMember) ,我尝试移动 1 从第一个列表框到第二个列表框的项目,我想要那个 所选项目也会从第一个列表框中删除:

    private void btnMoveRight_Click(object sender, EventArgs e)
    {
        ADD();

    }

    private void ADD()
    {
        int c = listJobBox.Items.Count - 1;

  ` for(int i= c; i>=0; i--)
        {
        if(listJobBox.GetSelected(i))
        {

        lstAssignedJobs.Items.Add(listJobBox.Items[i]);

            listJobBox.Items.Remove(listJobBox.SelectedItem); ---error line

但所选项目并未从第一个列表框中删除。

它显示错误消息“无法修改项目集合 设置 DataSource 属性时。”

谁能给我解决我的问题。

【问题讨论】:

  • 什么是数据源,您是否尝试将其从那里删除?
  • 在我的第一个列表框中,我正在从数据库上传数据
  • 这里是 listbox1 代码:pastie.org/9661587
  • 该代码显示了如何填写listWBox,但错误发生在listJobBox1。除此之外,您似乎使用DataTable 作为数据源。然后从中删除适当的DataRow
  • 出于安全考虑,我在这里更改了盒子的名称。 listJobBox1 与 listWBox 相同。但我没有使用数据行。我不明白你的意思。你能详细说明你的回答吗

标签: c# listbox


【解决方案1】:

向您的 DataTable 对象添加一个布尔列,例如 IsSelected

然后,不要将 listbox1 直接绑定到表,而是将其绑定到 BindingSource。使用设计器将 2 个绑定源添加到您的表单。并将此代码放在您的代码隐藏文件中。

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
        this.InitializeDataObjects();
    }

    private void InitializeDataObjects()
    {
        this.InitData();
        this.InitBindingSources();
    }

    private void InitData()
    {
        ds = new DataSet();
        var dt = new DataTable("Table1");
        dt.Columns.Add("Name", typeof(string));
        ds.Tables.Add(dt);
    }

    private void InitBindingSources()
    {
        bindingSource1 = new BindingSource();
        bindingSource2 = new BindingSource();

        bindingSource1.DataSource = ds;
        bindingSource1.DataMember = "Table1";
        bindingSource2.DataSource = ds;
        bindingSource2.DataMember = "Table1";

        listBox1.DataSource = bindingSource1;
        listBox1.DisplayMember = "Name";
        listBox2.DataSource = bindingSource2;
        listBox2.DisplayMember = "Name";
    }
}

然后,当您加载数据时,请执行以下操作:

    private void btnLoadAndBind_Click(object sender, EventArgs e)
    {
        this.FetchData(this.ds.Tables["Table1"]);
        this.AddSelectedColumn(this.ds.Tables["Table1"]);

        this.bindingSource1.Filter = "IsSelected = false";
        this.bindingSource2.Filter = "IsSelected = true";
    }

    private void FetchData(DataTable dataTable)
    {
        string CS = "your connectionstring";
        using (SqlConnection con = new SqlConnection(CS))
        {
            try
            {
                SqlDataAdapter da = new SqlDataAdapter();

                con.Open();
                var sqlcmd = new SqlCommand("SELECT Name FROM sometable", con);
                sqlcmd.CommandType = CommandType.Text;
                da.SelectCommand = sqlcmd;
                da.Fill(dataTable);
            }
            catch (Exception ex)
            {
                MessageBox.Show("exception raised");
                throw ex;
            }
        }
    }

    private void AddSelectedColumn(DataTable suppliersDataTable)
    {
        var dc = new DataColumn("IsSelected", typeof(bool));
        suppliersDataTable.Columns.Add(dc);

        foreach (DataRow dr in suppliersDataTable.Rows)
        {
            dr["IsSelected"] = false;
        }
    }    

现在您的列表框都连接到同一个数据表并根据 IsSelected 属性/列进行过滤。只需将此列设置为真或假,它就会从一个盒子翻转到另一个盒子。您的按钮事件处理程序可能如下所示:

public void button_Click(object sender, EventArgs e)
{
    if (this.bindingSource1.Current!= null)
    {
         var dr = ((DataRowView)this.bindingSource1.Current).Row;
         dr["IsSelected"] = true;
     }
}

这行得通!

如果您使用类型化的数据集,事情会变得更加简单。然后大部分绑定都可以在设计器中完成,您的代码将缩减到 20 行代码......

【讨论】:

  • 您是否真的测试了我的代码并试图让它工作? stackoverflow 并不是为了让其他人编写您的代码。我能够在 5 分钟内完成这项工作。基本思想仍然相同,并且开箱即用。我用完整的测试代码编辑了我的答案。希望您现在可以使用它。
【解决方案2】:

假设 listbox1 绑定到 datatable1(它可以是任何其他集合类型)并且 listbox2 绑定到 datatable2。当您单击移动按钮时,从集合中删除所选项目,即 datatable1 并将该项目添加到其他集合,即 datatable2 并重新绑定 listbox1 和 lisbox2。

【讨论】:

  • 你能举个例子吗
【解决方案3】:

这是一个粗略的工作示例:

public partial class Form1 : Form
{
    private DataTable _dataSource1;
    private DataTable _dataSource2;
    public Form1()
    {
        InitializeComponent();

        _dataSource1 = GetData1();
        _dataSource2 = GetData2();
        Initialize();
    }



    private void btnMove_Click(object sender, EventArgs e)
    {
        MoveItem();
    }

    void Initialize()
    {
        listBox1.DataSource = _dataSource1;
        listBox1.DisplayMember = "Fruits";
        listBox1.ValueMember = "Fruits";

        listBox2.DataSource = _dataSource2;
        listBox2.DisplayMember = "Fruits";
        listBox2.ValueMember = "Fruits";
    }

    DataTable GetData1()
    {
        var dt = new DataTable();
        dt.Columns.Add("Fruits");
        dt.Rows.Add(new object[] {"Apple"});
        dt.Rows.Add(new object[] { "Orange" });
        dt.Rows.Add(new object[] { "Grapes" });
        return dt;
    }
    DataTable GetData2()
    {
        var dt = new DataTable();
        dt.Columns.Add("Fruits");
        return dt;
    }

    void MoveItem()
    {
        var index = listBox1.SelectedIndex;
        var dataRowToRemove = _dataSource1.Rows[index];
        var listItem = dataRowToRemove[0] as string;
        _dataSource1.Rows.Remove(dataRowToRemove);


        var dataRowToAdd = _dataSource2.NewRow();
        dataRowToAdd[0] = listItem;
        _dataSource2.Rows.Add(dataRowToAdd); 
        Initialize();

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    • 2012-07-11
    相关资源
    最近更新 更多