方法1:微软提供的DataGridView主从表显示示例
http://www.cnblogs.com/NETCCB/articles/1335347.html
优点:前台不用写代码,都由BindingSource等控件实现。
缺点:填充到数据集中的子表的所有记录必须在主表中有对应数据。
方法2:是在DataGridView.RowEnter中写类似如下代码,
labCusId.Text = dgvCustomer.CurrentRow.Cells[col].Value.ToString();字段一多,这种方法就非常繁琐。
这里介绍另一种利用数据绑定实现数据联动的方法。
private void FillSaledgv(string CusIDStr)
{
dgvSale.DataSource = null;
DataSet sqlDS = new DataSet();
sqlDataAda.Fill(sqlDS,"vw_SaleInfo");
DataView sqlDV = sqlDS.Tables["vw_SaleInfo"].DefaultView;
if (sqlDS.Tables["vw_SaleInfo"].Rows.Count > 0)
{
dgvSale.DataSource = sqlDV;
}
BindSaleTxt(sqlDV);
sqlCon.Close();
}
private void BindSaleTxt(DataView sqlDV)
{
labSaleID.DataBindings.Clear();
labSaleIDDetail.DataBindings.Clear();
txtHWSaleIDDel.DataBindings.Clear();
dtpSaleBillDate.DataBindings.Clear();
if (sqlDV.Table.Rows.Count > 0)
{
labSaleID.DataBindings.Add("Text", sqlDV, "销售单ID");
labSaleIDDetail.DataBindings.Add("Text", sqlDV, "销售单ID");
txtHWSaleIDDel.DataBindings.Add("Text", sqlDV, "手工销售单号");
dtpSaleBillDate.DataBindings.Add("Value", sqlDV, "销售日期");
}
}
需要注意的是:dgvSale.DataSource = sqlDV; 和 BindSaleTxt(sqlDV);这里的数据源必须是一致的——如果是数据表,则必须是同一个表。
我之前是曾犯错误:
dgvSale.DataSource = sqlDS.Tables["vw_SaleInfo"];
BindSaleTxt(sqlDS.Tables["vw_SaleInfo"].DefaultView);
虽然各自能够取到数据,但labSaleID等显示控件不能随dgvSale联动。
Q:对于两个datagridView实现的数据联动,主datagridView绑定数据时selectionChanged事件发生多次,什么原因,如何避免?
A:selectionChanged事件MSDN上叙述:“在当前选择出现更改时发生。”
实际应用中,子表数据填充代码要写在selectionChanged事件响应方法中。
经测试,selectionChanged事件有如下规律:
SelectionChanged事件发生次数与触发方式和dataGridView中是否有数据有关。
1.由数据绑定触发,如果dataGridView中原来无数据,则SelectionChanged事件发生1次;(从没有选定行到有选定行。)
2.由数据绑定触发,如果dataGridView中原来有数据,则SelectionChanged事件发生2次;(取消选定行发生1次,选定新行发生1次。)
3.由用户(鼠标或键盘动作)触发,dataGridView中原来有数据,则SelectionChanged事件发生1次;
解决方法:设置一个开关变量
/// <summary>
/// 防止dgvIn数据绑定时发生多次SelectionChanged事件,设置开关变量
/// </summary>
private static byte SelectionChangedTimes;
每次数据绑定前设置开关变量的值
if (dgvIn.Rows.Count == 0)
SelectionChangedTimes = 1; // 无数据直接跨过阀值
else
SelectionChangedTimes = 0; // 有数据设定小于阀值
dgvIn.DataSource = dtIn;
// SelectionChanged中对开关变量进行判断,决定是否对子表进行数据绑定
private void dgvIn_SelectionChanged(object sender, EventArgs e)
{
if (++SelectionChangedTimes == 1)
return;
else
if (SelectionChangedTimes >= 255)
SelectionChangedTimes = 2; // 防止数据越界
if (null != dgvIn.CurrentRow)
{
// 对子表进行数据绑定
}
}