需求是这样,只有调整日期,调整金额两列能被修改,其余的列都不能被修改。日期格式要防止用户输错。数字输入了中文也要提示。
数据来源于存储过程里的视图,这里需要注意的一点是:datagridview采用adaptor绑定的数据,如果比如调整金额字段是数据类型的字段,那么在datagridview上这个字段下面输入文字,即使try catch或者 tryparse都会根本不进断点就报错了,我的做法是把这些日期,数字字段在视图上 用convert转为nvarchar类型的数据类型,这样改了之后就能自由的处理日期格式,数字转换错误了。
1、批量更新
我是这样做的,创建一个修改数据的类:clsUpdateRow,里面有id ,data1,data2 3个数据,id记录表的主键,data1作为调整日期......为datagridview做CellValueChanged事件,事件里面首先判断是否是能被修改的列。每次修改了就把clsUpdateRow放入list集合中,点击保存就循环这个集合。对于只读列,就用dgv_update.Columns[i].ReadOnly = true; 可修改列 改为 false就可以了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private void dgv_update_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
var dgv = sender as DataGridView;
string id = dgv["id", e.RowIndex].Value.ToString();
clsUpdateRow cls = listupdates.Find(l => l.id == id);
if (cls == null)
{
cls = new clsUpdateRow();
}
cls.id = id;
var d1 = ValidateCol(dgv["调整日期", e.RowIndex].Value);
var d2 = ValidateCol(dgv["调整金额", e.RowIndex].Value);
if (d1 != "")
{
DateTime dd = DateTime.Now;
if (!DateTime.TryParse(d1, out dd))
{
MessageBox.Show("日期输入不正确");
return;
}
}
if (d2 != "")
{
double ddd = 0.0;
if (!double.TryParse(d2, out ddd))
{
MessageBox.Show("请输入有效数字");
return;
}
}
cls.data1 = d1;
cls.data2 = d2;
listupdates.Add(cls);
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private void btn_save_Click(object sender, EventArgs e)
{
if (listupdates.Count < 1)
{
MessageBox.Show("没有要更改的数据");
return;
}
string sql = "update [uj_Funding_plan_auto] set tzdate={0},tzmoney={1} where id={2}";
List<SqlParameter> listps = new List<SqlParameter>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < listupdates.Count; i++)
{
var item = listupdates[i];
string tzdate = "@tzdate" + i;
string tzmoney = "@tzmoney" + i;
string id = "@id" + i;
sb.Append(string.Format(sql, tzdate, tzmoney, id) + "
");
SqlParameter p1 = new SqlParameter();
p1.ParameterName = tzdate;
if (item.data1.Trim() == "")
{
p1.Value = DBNull.Value;
}
else
{
p1.Value = item.data1;
}
SqlParameter p2 = new SqlParameter();
p2.ParameterName = tzmoney;
if (item.data2.Trim() == "")
{
p2.Value = DBNull.Value;
}
else
{
p2.Value = item.data2;
}
listps.Add(new SqlParameter(id, listupdates[i].id));
listps.Add(p1);
listps.Add(p2);
}
SqlHelper.ExecuteNonQuery(SqlHelper.ConnectionString, sb.ToString(), listps.ToArray());
listupdates.Clear();
btn_query.PerformClick();
}
2.日期设置 、指定列弹出右键菜单
在这个基础之上,我发现这个如果本来不填日期的,填了日期,想要清楚就无法做到了。我就加了一个右键菜单,专门用来清楚日期,而且这个也只能在日期这一列才能弹出菜单。具体的做法是这样的。
首先,控制菜单再指定列弹出。不要再datagridview里的控件属性里的ContextMenuStrip设置这个菜单,因为如果再这里设置了菜单的话,你不管点击哪一列,都会弹出这个菜单的。弹出的代码:
private void dgv_update_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex != dgv_update.Columns["调整日期"].Index) { return; } if (e.Button == MouseButtons.Right) { row = e.RowIndex; col = e.ColumnIndex; dgv_menu.Show(MousePosition.X, MousePosition.Y); } }
这里记录的row和col值,是在点击了清楚日期事件后找到这个单元格需要的。
dgv_update[col,row].Value = "";