【问题标题】:Update DataGridView based on Combobox value根据 Combobox 值更新 DataGridView
【发布时间】:2013-06-13 06:55:52
【问题描述】:

我有一个带有组合框和 datagridview 控件的表单。组合框由数据库表填充,并存储事务 ID。

当组合框更新时,Datagridview 绑定到一个数据库表,并显示与组合框中的事务 ID 关联的记录。

cboTransaction_SelectionChangeCommitted(object sender, EventArgs e)
{
    int id = Convert.ToInt32(cboTransaction.SelectedValue);
    db.Items.Where(i => i.TransactionId == id).Load();
    bs.DataSource = db.Items.Local.ToBindingList();
    dgv.DataSource = bs;
}

对于第一条记录,这很好用。用户可以毫无问题地在 DataGridView 中选择事务 ID 并添加/编辑项目记录。

但是,当用户从组合框中选择不同交易时,事情会变得有点混乱。使用上面的代码,DataGridView 不会清除具有旧 ID 号的行,而是显示旧记录 + 新选择的 Transaction 的任何记录。我假设 Where() 子句会将 DataGridView 限制为事务 ID 匹配的那些项目。

如果我将db.SaveChanges();dgv.Rows.Clear(); 添加到该块的开头,则会成功清除行,但不会将更改保存到数据库中。

我也试过了

db.Items.Load();
bs.DataSource = db.Items.Local.ToBindingList().Where(i => i.TransactionId == id);

这会将 Datagridview 绑定到正确的事务,但不允许用户添加任何记录。

如何确保 datagridview 仅显示与所需事务相关的记录,同时仍允许用户添加/编辑记录?

编辑

我创建了一个带有文本框、按钮和 datagridview 的测试表单进行测试,结果相同。 Datagridview 有一个正在编辑的数据库表的数据源。

public partial class frmTest : Form
{
private BindingSource bs = new BindingSource();
private UniformDataContainer db = new UniformDataContainer();
public frmTest()
{
    InitializeComponent();
    dataGridView1.DataSource = bs;
}

private void button1_Click(object sender, EventArgs e)
{
    int id = Convert.ToInt32(textBox1.Text.ToString());
    db.Items.Where(i => i.TransactionId == id).Load();
    bs.DataSource = db.Items.Local.ToBindingList();

    bs.ResetBindings(false);
}

private void dataGridView1_RowValidated(object sender, DataGridViewCellEventArgs e)
{
    db.SaveChanges();
}
}

在调试代码时,我发现db.Items.Local 仍然包含旧行,并且似乎没有清除。

【问题讨论】:

    标签: c# winforms datagridview combobox


    【解决方案1】:

    不要在更改后将DataSource 重新绑定到DataGridView,而是调用应该使用新值重置网格的ResetBindings 方法。

    cboTransaction_SelectionChangeCommitted(object sender, EventArgs e)
    {
        int id = Convert.ToInt32(cboTransaction.SelectedValue);
    
        db.Items.Where(i => i.TransactionId == id).Load();
        bs.DataSource = db.Items.Local.ToBindingList();
    
        bs.ResetBindings(false);
    }
    

    试试看是否解决了你的问题,如果没有,我还有一个建议,但这应该可以完成工作:)

    编辑

    好的,在您编辑后,我看到了问题。首先,您必须清除 DB 类的本地缓存或绑定到您的 where 子句:

    cboTransaction_SelectionChangeCommitted(object sender, EventArgs e)
    {
        int id = Convert.ToInt32(cboTransaction.SelectedValue);
    
        var bindinglist = new BindingList(db.Items.Where(i => i.TransactionId == id).ToList());
        bs.DataSource = bindinglist;
    
        bs.ResetBindings(false);
    }
    

    【讨论】:

    • 恐怕运气不好。我为测试创建了一个单独的表单(请参阅上面的编辑问题),但 datagridview 仍然显示以前的记录。我还注意到 db.Items.Local 仍然保存以前的数据库记录。
    • 您的编辑会清除数据网格视图,但不会将新记录添加到数据库中。我胡思乱想,以为我已经使用了db.Items.Local.Clear(),但它只会保存最近添加的记录。
    【解决方案2】:

    在设置之前必须将网格的DataSource设置为null。像这样:

    cboTransaction_SelectionChangeCommitted(object sender, EventArgs e)
    {
        int id = Convert.ToInt32(cboTransaction.SelectedValue);
        db.Items.Where(i => i.TransactionId == id).Load();
        bs.DataSource = db.Items.Local.ToBindingList();
        dgv.DataSource = null;
        dgv.DataSource = bs;
    }
    

    【讨论】:

    • 这不会在id 更改时删除以前的记录。
    【解决方案3】:

    我设法通过处理我的 Database Conext 并重新连接来修复它/破解它:

    db.Dispose();
    db = new UniformDataContainer();
    int id = Convert.ToInt32(textBox1.Text);
    db.Items.Where(i => i.TransactionId == id).Load();
    bs.DataSource = db.Items.Local.ToBindingList();
    

    这会保存先前交易的现有记录,并在选择新交易后清除数据网格。

    感谢@gzaxx 和@SerkanOzvatan 的回复!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-05
      • 2021-09-13
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多