根据Combobox值更新DataGridView

时间:2013-06-13 06:55:53

标签: c# winforms datagridview combobox

我有一个带有组合框和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;
}

对于第一条记录,这很好用。用户可以选择事务ID并在DataGridView中添加/编辑Item记录而不会出现问题。

但是,当用户从组合框中选择不同的事务时,事情会变得有点麻烦。使用上面的代码,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仍包含旧行,但似乎并不清楚。

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

在设置之前,必须将网格的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;
}

答案 2 :(得分:0)

我设法通过处理我的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的回复!