c# 之winform 可编辑table 踩过的坑

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c# 之winform 可编辑table 踩过的坑相关的知识,希望对你有一定的参考价值。


界面图:

c#

完整代码: [数据库交互和一些工具类等忽略 只看逻辑]

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using System.Windows.Forms;
using ess_zbfz_main.commonForm;
using ess_zbfz_main.dto;
using ess_zbfz_main.entity;
using ess_zbfz_main.ifs;
using ess_zbfz_main.util;
using ess_zbfz_main.vo;
using ess_zbfz_main.zhaobiao;
using Newtonsoft.Json;
using PublicLibrary;

namespace ess_zbfz_main.baseInfoFrm

public partial class FrmBzjAdd : Form,UploadCommonIFS

private static string sqliteDbName = ConfigurationManager.AppSettings["sqliteDBName"].ToString(); //数据库名称
private static string sqliteDbLocation = ConfigurationManager.AppSettings["sqliteDBLocation"].ToString(); //数据库存放路径

//保存接口
internal static string apiSave = "oszbsupplierdeposit/save";


//更新附件信息
internal static string apiUpdateFile = "oszbsupplierdeposit/updateFile";


//当前的项目信息
private OsZbPurchaseProjectInfo currentProjectInfo;


//保证金信息
private OsZbSupplierDeposit currentDeposit;

//保证金详情信息
private List<OsZbSupplierDepositDetail> detailList;

//标下拉
private List<ComboBoxVo> markList;

//点击时间
public DateTime clickTime;

//当前行
private int currentRow =0;

public FrmBzjAdd()

InitializeComponent();


public FrmBzjAdd(OsZbPurchaseProjectInfo currentProjectInfo, OsZbSupplierDeposit osZbSupplierDeposit)

this.currentProjectInfo = currentProjectInfo;
this.currentDeposit = osZbSupplierDeposit;
InitializeComponent();



private void FrmBzjAdd_Load(object sender, EventArgs e)

this.supplierName.Text = PublicVo.SupplyName;
this.projectName.Text = currentProjectInfo.ProjectName;
this.projectNo.Text = currentProjectInfo.ProjectNo;
this.listDataGriddView.AutoGenerateColumns = false;

//按键
this.totalMoney2.KeyPress += Main_KeyPress;
this.totalInsure.KeyPress += Main_KeyPress;
//失焦事件
this.totalMoney2.LostFocus += Main_LostFocus;
this.totalInsure.LostFocus += Main_LostFocus;

//02物资类到标段填写,01服务类到包填写
if (currentProjectInfo!=null && currentProjectInfo.PurchaseType == "02")

this.listDataGriddView.Columns["packName"].Visible = false;


LoadData(null);


private void Main_LostFocus(object sender, EventArgs e)

try

TextBox textBox = (TextBox)sender;

string value = textBox.Text;
if (value != null && value.ToString().EndsWith("."))

string valueTxt = value.Substring(0, value.Length-1);
textBox.Text = valueTxt;

if (!string.IsNullOrEmpty(this.totalMoney2.Text) &&
!string.IsNullOrEmpty(this.totalInsure.Text))

decimal total = Decimal.Add(Convert.ToDecimal(this.totalMoney2.Text), Convert.ToDecimal(this.totalInsure.Text));
this.total.Text = total.ToString();


catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);



private void Main_KeyPress(object sender, KeyPressEventArgs e)

try

TextBox textBox = (TextBox)sender;

int start = textBox.SelectionStart;
int len = textBox.SelectionLength;

string text = "";
if (len > 0)

text = textBox.Text.Substring(0, start) + e.KeyChar.ToString() + textBox.Text.Substring(start + len - 1, textBox.Text.Length - start - len);

else

text = textBox.Text + e.KeyChar.ToString();


string pattern = @"^([1-9]\\d0,12|0)(\\.\\d0,3)?$";

if ("\\b".Equals(e.KeyChar.ToString()) || "\\r".Equals(e.KeyChar.ToString()) || "\\t".Equals(e.KeyChar.ToString()))

return;


if (!Regex.IsMatch(text, pattern))

e.Handled = true;


catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);




/// <summary>
/// 加载数据
/// </summary>
/// <param name="flag"></param>
public void LoadData(string flag)

try

if(this.Owner is FrmBzj)

FrmBzj frmBzj= (FrmBzj)this.Owner;
//刷新父窗口的方法
frmBzj.RefreshSelf();


this.listDataGriddView.DataSource = null;
//查询标下拉信息
string markComboboxSql = "select OS_ZB_PURCHASE_PROJECT_INFO.MARK_NO as keyValue,OS_ZB_PURCHASE_PROJECT_INFO.MARK_NAME as keyName from OS_ZB_PURCHASE_PROJECT_INFO where OS_ZB_PURCHASE_PROJECT_INFO.PROJECT_NO =" + currentProjectInfo.ProjectNo + " group by OS_ZB_PURCHASE_PROJECT_INFO.MARK_NO ";
markList = SQLiteLibrary.SelectBySql<ComboBoxVo>(sqliteDbLocation, sqliteDbName, markComboboxSql);

string defaultPattern = "yyyy-MM-dd";
DateUtil.SetDatePick(ref this.yxq, defaultPattern, true, DatePickChange);

//修改页面
if (currentDeposit != null)

string mainSql = "SELECT OS_ZB_SUPPLIER_DEPOSIT.*,OS_ZB_PURCHASE_PROJECT_INFO.PROJECT_NAME,SYS_FILE_INFO.FILE_PATH FROM OS_ZB_SUPPLIER_DEPOSIT";
mainSql += " left join OS_ZB_PURCHASE_PROJECT_INFO ON OS_ZB_PURCHASE_PROJECT_INFO.PROJECT_NO =OS_ZB_SUPPLIER_DEPOSIT.PROJECT_NO";
mainSql += " left join SYS_FILE_INFO on SYS_FILE_INFO.ID =OS_ZB_SUPPLIER_DEPOSIT.ATTACH_ID ";
mainSql += " where OS_ZB_SUPPLIER_DEPOSIT.id=" + currentDeposit.Id + "";
List<OsZbSupplierDeposit> lists = SQLiteLibrary.SelectBySql<OsZbSupplierDeposit>(sqliteDbLocation, sqliteDbName, mainSql);
currentDeposit = lists.Count > 0 ? lists[0] : null;


if ("baodan".Equals(currentDeposit.VoucherCategory))

currentDeposit.VoucherCategory = "保单";

else if ("huikuan".Equals(currentDeposit.VoucherCategory))

currentDeposit.VoucherCategory = "汇款";



//给主页面部分设置信息
SetPageMainInfo(this.groupBox1, currentDeposit);
//投保方式 不能修改
this.payWay.Enabled = false;

this.AddRowBtn.Visible = currentDeposit.Sfanjn != "YES";


//上传的图片
if (!StringUtil.IsEmpty(currentDeposit.FilePath))

currentDeposit.FilePath =LocalFileUtil.GetPath(currentDeposit.FilePath);
Image image = new Bitmap(currentDeposit.FilePath);
this.pictureBox1.Image =new Bitmap(image, 300, 300);



//this.pictureBox1.Image = new
this.totalMoney2.Text = currentDeposit.TotalMoney;

string secordSql = "select OS_ZB_SUPPLIER_DEPOSIT_DETAIL.*,OS_ZB_PURCHASE_PROJECT_INFO.MARK_NAME,No AS isAddRow from OS_ZB_SUPPLIER_DEPOSIT_DETAIL";
secordSql += " left join OS_ZB_SUPPLIER_DEPOSIT on OS_ZB_SUPPLIER_DEPOSIT.ID = OS_ZB_SUPPLIER_DEPOSIT_DETAIL.PARENT_ID";
secordSql += " left join OS_ZB_PURCHASE_PROJECT_INFO on OS_ZB_PURCHASE_PROJECT_INFO.PROJECT_NO = OS_ZB_SUPPLIER_DEPOSIT.PROJECT_NO and OS_ZB_SUPPLIER_DEPOSIT_DETAIL.MARK_NO = OS_ZB_PURCHASE_PROJECT_INFO.MARK_NO";
secordSql += " where OS_ZB_SUPPLIER_DEPOSIT_DETAIL.PARENT_ID = " + currentDeposit.Id + " group by OS_ZB_SUPPLIER_DEPOSIT_DETAIL.ID";

detailList = SQLiteLibrary.SelectBySql<OsZbSupplierDepositDetail>(sqliteDbLocation, sqliteDbName, secordSql);

for (int i = 0; i < detailList.Count; i++)

detailList[i].DepositMoney = string.IsNullOrEmpty(detailList[i].DepositMoney) ? "0" : detailList[i].DepositMoney;
detailList[i].TotalMoney = string.IsNullOrEmpty(detailList[i].TotalMoney) ? "0" : detailList[i].TotalMoney;
detailList[i].DepositInsure = string.IsNullOrEmpty(detailList[i].DepositInsure) ? "0" : detailList[i].DepositInsure;


else


this.panelActive.Visible = false;



//标的下拉选项
DataGridViewColumn dataGridViewColumn = this.listDataGriddView.Columns["markNo"];
if (dataGridViewColumn is DataGridViewComboBoxColumn)

DataGridViewComboBoxColumn comboBoxColum = (DataGridViewComboBoxColumn)dataGridViewColumn;

ComboBoxVo comboBoxVo = new ComboBoxVo("", "请选择");
markList.Insert(0, comboBoxVo);

comboBoxColum.DataSource = markList;

comboBoxColum.ValueMember = "keyName";
comboBoxColum.DisplayMember = "keyValue";




detailList = detailList != null && detailList.Count > 0 ? detailList : new List<OsZbSupplierDepositDetail>();
detailList.Insert(0, new OsZbSupplierDepositDetail());
this.listDataGriddView.DataSource = detailList;

// 移除空白项
this.listDataGriddView.DataSource = null;//必须要
detailList.RemoveAt(0);
this.listDataGriddView.DataSource = detailList;

if (detailList != null && detailList.Count>0)

this.listDataGriddView.Columns["packName"].DataPropertyName = "packName";



catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);





/// <summary>
/// 主页面设置值
/// </summary>
/// <param name="mainControl"></param>
/// <param name="currentDeposit"></param>
private void SetPageMainInfo(Control mainControl, OsZbSupplierDeposit currentDeposit)

var allControls = mainControl.Controls;

for (int i = 0; i < allControls.Count; i++)
if (allControls[i] is TextBox || allControls[i] is DateTimePicker || allControls[i] is ComboBox)

SetControlValueByEntity(currentDeposit, currentDeposit.GetType(), allControls[i]);

if (allControls[i] is CheckBox)

((CheckBox)allControls[i]).Checked = currentDeposit.Sfanjn == "YES";





/// <summary>
/// 给控件设置值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <param name="type"></param>
/// <param name="control"></param>
private void SetControlValueByEntity<T>(T t, Type type, Control control)

string propName = StringUtil.UpperCaseFirst(control.Name);

BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

PropertyInfo propertyInfo = type.GetProperty(propName, bindingFlags);

if (propertyInfo != null)

object value =propertyInfo.GetValue(t);
control.Text = value!=null?value.ToString():null;


/* else if (propertyInfo == null && "DepositInsure".Equals(propName))//保险可为0

propertyInfo.SetValue(t, "0");
*/





/// <summary>
/// 全选和全不选
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAllCheck_Click(object sender, EventArgs e)

string tag = this.btnAllCheck.Tag.ToString();
//结束编辑
this.listDataGriddView.EndEdit();
bool check = false;
//全选
if (tag == "checkAll")

check = true;


int count = Convert.ToInt16(listDataGriddView.Rows.Count.ToString());
for (int i = 0; i < count; i++)

DataGridViewCheckBoxCell selectCheckCell = (DataGridViewCheckBoxCell)listDataGriddView.Rows[i].Cells["select_check"];
//bool flag = Convert.ToBoolean(selectCheckCell.Value);
selectCheckCell.Value = check;


//
if (tag == "checkAll")

this.btnAllCheck.Text = "全不选";
this.btnAllCheck.Tag = "unAllcheck";
this.btnAllCheck.Image = Properties.Resources.all_uncheck_20;
this.btnAllCheck.Width += 6;

else

this.btnAllCheck.Text = "全选";
this.btnAllCheck.Tag = "checkAll";
this.btnAllCheck.Image = Properties.Resources.all_check_20;
this.btnAllCheck.Width -= 6;






/// <summary>
/// 删除功能 --- UI删除行 不操作数据库
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnDelete_Click(object sender, EventArgs e)

try

int count = Convert.ToInt16(listDataGriddView.Rows.Count.ToString());

//物理新增的行
List<int> deleteRows = new List<int>();

//绑定数据源的行
List<OsZbSupplierDepositDetail> dataSourceRows = new List<OsZbSupplierDepositDetail>();

for (int i = 0; i < count; i++)

if ((bool)listDataGriddView.Rows[i].Cells[0].EditedFormattedValue == true)

if (detailList!=null && detailList.Count> i)

dataSourceRows.Add(detailList[i]);

else

deleteRows.Add(i);




if (deleteRows.Count <= 0 && dataSourceRows.Count<=0)

MessageBox.Show("请选择需要删除的数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);


for (int i = 0; i < deleteRows.Count; i++)

//this.listDataGriddView.Rows.
this.listDataGriddView.Rows.RemoveAt(deleteRows[i]);


for (int i = 0; i < dataSourceRows.Count; i++)

detailList.Remove(dataSourceRows[i]);


if (dataSourceRows.Count > 0)

this.listDataGriddView.DataSource = null;//必须要
this.listDataGriddView.DataSource = detailList;


//计算
CalMoney(-1);

catch (Exception ex)

MessageBox.Show("刪除异常,错误信息:" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);



//刷新
private void btnRefesh_Click(object sender, EventArgs e)

LoadData(null);




/// <summary>
/// 新增行事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddRowBtn_Click(object sender, EventArgs e)

object dataSource = this.listDataGriddView.DataSource;
this.listDataGriddView.Enabled = false;
//this.listDataGriddView.AllowUserToAddRows = true;
//如果绑定了数据源 需要先取消绑定
if (dataSource is List<OsZbSupplierDepositDetail>)

List<OsZbSupplierDepositDetail> detailList =(List<OsZbSupplierDepositDetail>)this.listDataGriddView.DataSource;
OsZbSupplierDepositDetail detail = new OsZbSupplierDepositDetail();
detailList.Add(detail);
this.listDataGriddView.DataSource = null;
this.listDataGriddView.DataSource = detailList;

else

this.listDataGriddView.Rows.Add();//新增行

this.listDataGriddView.Enabled = true;




/// <summary>
/// 计算金额部分
/// </summary>
private void CalMoney(int curRow)

try

int rowCount = this.listDataGriddView.Rows.Count;

//行--保证金总额
Decimal rowTotal = new Decimal();

//顶部统计 保证金总额 保险总额 总金额
Decimal totalBzj = new Decimal();
Decimal totalBx = new Decimal();
Decimal total = new Decimal();

for (int i = 0; i < rowCount; i++)


rowTotal = AddCalByRows(this.listDataGriddView.Rows[i].Cells["depositMoney"], this.listDataGriddView.Rows[i].Cells["depositInsure"]);

totalBzj = Decimal.Add(totalBzj, GetFormateValue(this.listDataGriddView.Rows[i].Cells["depositMoney"]));

totalBx = Decimal.Add(totalBx, GetFormateValue(this.listDataGriddView.Rows[i].Cells["depositInsure"]));

total = Decimal.Add(total, rowTotal);

//改变事件的触发行 【不需要设置curRow写-1】
if (curRow == i)

this.listDataGriddView.Rows[i].Cells["totalMoney"].Value = rowTotal;




this.totalMoney2.Text = totalBzj.ToString();

this.totalInsure.Text = totalBx.ToString();

this.total.Text = total.ToString();

catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
//throw;



/// <summary>
/// 计算两个单元格值的和
/// </summary>
/// <param name="cell1"></param>
/// <param name="cell2"></param>
/// <returns></returns>
private decimal AddCalByRows(DataGridViewCell cell1, DataGridViewCell cell2)


return Decimal.Add(GetFormateValue(cell1), GetFormateValue(cell2));



/// <summary>
/// 设置单元格的值
/// </summary>
/// <param name="cell"></param>
/// <returns></returns>
private decimal GetFormateValue(DataGridViewCell cell)

Decimal val1 = Decimal.Zero;
if (cell.Value != null)

val1 = Convert.ToDecimal(cell.Value.ToString());

return val1;




//单元格修改完毕
private void listDataGriddView_CellEndEdit(object sender, DataGridViewCellEventArgs e)

try

if (e.RowIndex < 0 || e.ColumnIndex<0)

return;

//计算
CalMoney(e.RowIndex);

if (this.listDataGriddView.Columns[e.ColumnIndex].Name == "markNo")

DataGridViewCell dataGridViewCell = this.listDataGriddView.CurrentRow.Cells["markNo"];

object o = dataGridViewCell.Value;

int markNoIndex =this.listDataGriddView.Columns["markName"].Index;
this.listDataGriddView.CurrentRow.Cells["markName"].Value = o;
this.listDataGriddView.UpdateCellValue(markNoIndex, e.RowIndex);// 强制更新这个单元格的数据
string markNo = "";

if (dataGridViewCell is DataGridViewComboBoxCell)

DataGridViewComboBoxCell.ObjectCollection objectCollection = ((DataGridViewComboBoxCell)dataGridViewCell).Items;
for (int i = 0; i < objectCollection.Count; i++)

if (objectCollection[i] is ComboBoxVo && ((ComboBoxVo)objectCollection[i]).KeyName== o)

markNo = ((ComboBoxVo)objectCollection[i]).KeyValue;
this.listDataGriddView.CurrentRow.Cells["markNo_R"].Value = markNo;





if (o != null && o.ToString() != null && !"请选择".Equals(o.ToString()))

//分标名称

//查询标下拉信息
//+ " and OS_ZB_PURCHASE_PROJECT_INFO.SIGN_UP=YES
string packComboboxSql = "select OS_ZB_PURCHASE_PROJECT_INFO.PACK_NO as keyName,OS_ZB_PURCHASE_PROJECT_INFO.PACK_NAME as keyValue from OS_ZB_PURCHASE_PROJECT_INFO where OS_ZB_PURCHASE_PROJECT_INFO.MARK_NO =" + markNo + " order by PACK_NAME";
List<ComboBoxVo> packList = SQLiteLibrary.SelectBySql<ComboBoxVo>(sqliteDbLocation, sqliteDbName, packComboboxSql);

DataGridViewColumn column = this.listDataGriddView.Columns["packName"];

if (column is DataGridViewComboBoxColumn)

DataGridViewComboBoxCell boxCell = new DataGridViewComboBoxCell();

DataGridViewComboBoxColumn comboBoxColum = (DataGridViewComboBoxColumn)column;
List<string> pklist = new List<string>();
for (int i = 0; i < packList.Count; i++)

pklist.Add(packList[i].KeyValue);


if(pklist!=null && pklist.Count > 0)

pklist.Insert(0, "请选择");

else

pklist.Insert(0, "暂无数据");


boxCell.DataSource = pklist;
//boxCell.Value = e.RowIndex< detailList.Count?detailList[e.RowIndex].PackName:"";
//分包信息
this.listDataGriddView.CurrentRow.Cells[3] = boxCell;




catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);





/// <summary>
/// 保存提交操作
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSave_Click(object sender, EventArgs e)


R result = null;

//结束编辑
this.listDataGriddView.EndEdit();
this.btnSave.Focus();
//this.totalMoney2.LostFocus;

try

//主键id
string primaryKey = System.Guid.NewGuid().ToString("N");

//修改
if (currentDeposit != null && currentDeposit.Id!=null)

primaryKey = currentDeposit.Id;



var controls = this.groupBox1.Controls;

OsZbSupplierDeposit osZbSupplierDeposit = new OsZbSupplierDeposit();

for (int i = 0; i < controls.Count; i++)

if (controls[i] is TextBox || controls[i] is ComboBox || controls[i] is DateTimePicker)

SetValueByControl(osZbSupplierDeposit, osZbSupplierDeposit.GetType(), controls[i]);


osZbSupplierDeposit.SupplierId = PublicVo.SupplyId;
osZbSupplierDeposit.Id = primaryKey;
osZbSupplierDeposit.TotalMoney = this.totalMoney2.Text;
osZbSupplierDeposit.Sfanjn = this.sfanjn.Checked ? "YES" : "NO";
if (currentDeposit != null && currentDeposit.Id != null)

osZbSupplierDeposit.AttachId = currentDeposit.AttachId;


List<OsZbSupplierDepositDetail> detailList = GetDataGridInfo(primaryKey,true);

if(osZbSupplierDeposit.Remark != null && osZbSupplierDeposit.Remark.Length > 500)

MessageBox.Show("备注内容长度最大为500个字符", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;



if (osZbSupplierDeposit.Sfanjn!="YES" && detailList.Count <= 0)

MessageBox.Show("至少需要填写一条详情数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;

//验证
MessageInfo<OsZbSupplierDepositDetail> messageInfo = VerifyUtil.Verify(detailList, "baozhengjin", true, "");

if (osZbSupplierDeposit.Sfanjn == "YES")

MessageInfo<OsZbSupplierDeposit> verifyMain = VerifyUtil.Verify(osZbSupplierDeposit, "baozhengjin");
if (verifyMain.ExistError)

messageInfo.ExistError = true;
messageInfo.ErrorInfo = verifyMain.ErrorInfo+"\\n"+messageInfo.ErrorInfo;



Dictionary<string, string> checkRepeat = new Dictionary<string, string>();

StringBuilder sbfInfo = new StringBuilder();

string checkField1 = "";
string checkField2= "";
string checkMsg= currentProjectInfo.PurchaseType == "02"?"标":"包";
for (var i = 0; i < detailList.Count; i++)

//01 服务 02物资 物资类到标段填写,服务类到包填写
checkField1 = currentProjectInfo.PurchaseType == "02" ? detailList[i].MarkNo : (detailList[i].PackName=="请选择"?"":detailList[i].PackName);
checkField2 = currentProjectInfo.PurchaseType == "02" ? detailList[i].MarkNo : detailList[i].MarkNo + "-" + (detailList[i].PackName == "请选择" ? "" : detailList[i].PackName);
if (string.IsNullOrEmpty(checkField1))

sbfInfo.Append($"第i + 1行 该checkMsg信息的未填写\\n");
messageInfo.ExistError = true;


if (checkRepeat.ContainsKey(checkField2))

sbfInfo.Append($"第i + 1行 该checkMsg信息的重复填写\\n");
messageInfo.ExistError = true;

else

checkRepeat.Add(checkField2, "");


messageInfo.ErrorInfo += sbfInfo.ToString();

if (messageInfo.ExistError && !StringUtil.IsBlack(messageInfo.ErrorInfo))

MessageBox.Show(messageInfo.ErrorInfo, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);

return;


osZbSupplierDeposit.ListData = detailList;


result = WebRequestUtil.PostBasicEntityDataApi(apiSave, osZbSupplierDeposit);

if (!result.Successful)

MessageBox.Show(result.ResultHint, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;



string mainSql = "";

//修改
if (currentDeposit != null && currentDeposit.Id != null)

mainSql = SQLiteSqlUtils.CreateUpdateSql(osZbSupplierDeposit, new string[] "id" );

//删除副表信息
string deleteDetailSql = "delete from OS_ZB_SUPPLIER_DEPOSIT_DETAIL where OS_ZB_SUPPLIER_DEPOSIT_DETAIL.PARENT_ID="+ primaryKey + "";
SQLiteLibrary.ExecuteSqlByTransaction(sqliteDbLocation, sqliteDbName, new string[] mainSql, deleteDetailSql );

if (detailList != null && detailList.Count > 0)

string insertDetailSql = SQLiteSqlUtils.CreateInsertSql(detailList);
SQLiteLibrary.insertData(sqliteDbLocation, sqliteDbName, insertDetailSql);


else

//新增
mainSql = SQLiteSqlUtils.CreateInsertSql(osZbSupplierDeposit);
SQLiteLibrary.insertData(sqliteDbLocation, sqliteDbName, mainSql);
if (detailList!=null && detailList.Count > 0)

string insertDetailSql = SQLiteSqlUtils.CreateInsertSql(detailList);
SQLiteLibrary.insertData(sqliteDbLocation, sqliteDbName,insertDetailSql);



MessageBox.Show("保存成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

LoadData(null);

this.Hide();
this.Close();

catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);




/// <summary>
/// 获取datagridView的值
/// </summary>
/// <returns></returns>
private List<OsZbSupplierDepositDetail> GetDataGridInfo(string relPrimaryKey,bool idAuto)

List<OsZbSupplierDepositDetail> detailList = new List<OsZbSupplierDepositDetail>();
try

DataGridView dataGridView = this.listDataGriddView;
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic;

PropertyInfo propertyInfo = null;

int rowCount = dataGridView.Rows.Count;

int columCount = dataGridView.Columns.Count;

OsZbSupplierDepositDetail depositDetail = null;
//行
for (int i = 0; i < rowCount; i++)

depositDetail = new OsZbSupplierDepositDetail();
//列
for (int k = 0; k < columCount; k++)

SetObjValue(depositDetail, depositDetail.GetType(),
dataGridView.Columns[k].Name, dataGridView.Rows[i].Cells[k]);



//设置主键的值
if (!StringUtil.IsEmpty(relPrimaryKey))


propertyInfo = depositDetail.GetType().GetProperty("ParentId", bindingFlags);
if (propertyInfo != null)

propertyInfo.SetValue(depositDetail, relPrimaryKey);



//注解自动设置
if (idAuto)

propertyInfo = depositDetail.GetType().GetProperty("Id", bindingFlags);
if (propertyInfo != null)

propertyInfo.SetValue(depositDetail, System.Guid.NewGuid().ToString("N"));



depositDetail.MarkNo = depositDetail.MarkNo_R;
detailList.Add(depositDetail);


catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);

return detailList;


/// <summary>
/// datagridView 取值 封装成数组对象=== 一行一行的设置
/// </summary>
/// <param name="depositDetail"></param>
/// <param name="type"></param>
/// <param name="name"></param>
/// <param name="dataGridViewCell"></param>
private void SetObjValue<T>(T t, Type type, string name, DataGridViewCell dataGridViewCell)

string propName = StringUtil.UpperCaseFirst(name);

if (dataGridViewCell.Value != null)

string textValue = dataGridViewCell.Value.ToString();
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
PropertyInfo propertyInfo = type.GetProperty(propName, bindingFlags);

if (propertyInfo != null)

if ("DepositInsure".Equals(propName) && string.IsNullOrEmpty(textValue))//保险可为0

propertyInfo.SetValue(t, "0");

else

propertyInfo.SetValue(t, textValue);



else

if ("DepositInsure".Equals(propName))//保险可为0

PropertyInfo propertyInfo = type.GetProperty(propName);
propertyInfo.SetValue(t, "0");





/// <summary>
/// 给对象设置值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <param name="type"></param>
/// <param name="control"></param>
private void SetValueByControl<T>(T t, Type type, Control control)

string propName = StringUtil.UpperCaseFirst(control.Name);

string textValue = control.Text;

BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

PropertyInfo propertyInfo = type.GetProperty(propName, bindingFlags);

if (propertyInfo != null)

propertyInfo.SetValue(t, textValue);


else if (propertyInfo == null && "DepositInsure".Equals(propName))//保险可为0

propertyInfo.SetValue(t, "0");




/// <summary>
/// 重新定义编辑框
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listDataGriddView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)

e.Control.Controls.Clear();

int colum = this.listDataGriddView.CurrentCell.ColumnIndex;
string columName = this.listDataGriddView.Columns[colum].Name;

if(e.Control is DataGridViewTextBoxEditingControl)

if (columName == "payTime")

DateTimePicker btn = new DateTimePicker();
e.Control.Controls.Add(btn);
btn.Dock = DockStyle.Fill;
btn.Cursor = Cursors.Default;
btn.Format = DateTimePickerFormat.Custom;
btn.CustomFormat = "yyyy-MM-dd";
TableVo tableVo = new TableVo(this.listDataGriddView.CurrentCell.RowIndex, colum);
btn.Tag = tableVo;//记录编辑的行和列
btn.ValueChanged += SetCellValue;

var cellValue = this.listDataGriddView.CurrentCell.Value;
//btn.MaxDate = DateTime.Now;

string pattern = @"\\d4[/-]\\d1,2[/-]\\d1,2";
Regex regex = new Regex(pattern);

var defaultValue = DateTime.Now.ToString();
defaultValue = regex.IsMatch(defaultValue) ? regex.Match(defaultValue).Groups[0].ToString() : defaultValue;
this.listDataGriddView.CurrentCell.Value = cellValue != null ? cellValue : defaultValue;
btn.Value = Convert.ToDateTime(this.listDataGriddView.CurrentCell.Value.ToString());
//this.listDataGriddView.Rows[].Cells[this.listDataGriddView.CurrentColumn].Value = curValue;


else if ("depositMoney".Equals(columName) || "depositInsure".Equals(columName) || "totalMoney".Equals(columName))


DataGridViewTextBoxEditingControl dgvTxt = (DataGridViewTextBoxEditingControl)e.Control; // 赋值
//dgvTxt.Name = columName;
dgvTxt.KeyPress -= Cells_KeyPress; // 移除事件 //dgvTxt.SelectAll();
dgvTxt.KeyPress += Cells_KeyPress; // 绑定到事件

//先让编辑框聚焦
dgvTxt.Focus();
//设置光标的位置到文本尾
dgvTxt.Select(dgvTxt.TextLength, 0);
//滚动到控件光标处
dgvTxt.ScrollToCaret();


else

DataGridViewTextBoxEditingControl dgvTxt = (DataGridViewTextBoxEditingControl)e.Control; // 赋值
dgvTxt.KeyPress -= Cells_KeyPress; // 移除事件







/// <summary>
/// 自定义的日历 改变值事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SetCellValue(object sender, EventArgs e)

DateTimePicker btn = (DateTimePicker)sender;
if(btn.Tag is TableVo)

TableVo tableVo = (TableVo)btn.Tag;
object value = btn.Value;
string curValue = "";
Console.WriteLine("当前值:"+ value);
if (value != null)

string pattern = @"\\d4[/-]\\d1,2[/-]\\d1,2";
Regex regex = new Regex(pattern);

curValue = btn.Value.ToString();
curValue = regex.IsMatch(curValue) ? regex.Match(curValue).Groups[0].ToString() : curValue;


this.listDataGriddView.Rows[tableVo.CurrentRow].Cells[tableVo.CurrentColumn].Value = curValue;




private void Cells_KeyPress(object sender, KeyPressEventArgs e)

DataGridViewTextBoxEditingControl dgvTxt = (DataGridViewTextBoxEditingControl)sender;
int start = dgvTxt.SelectionStart;
int len = dgvTxt.SelectionLength;

string text = "";
if (len > 0)

text = dgvTxt.Text.Substring(0, start) + e.KeyChar.ToString() + dgvTxt.Text.Substring(start + len - 1, dgvTxt.Text.Length - start - len);

else

text = dgvTxt.Text + e.KeyChar.ToString();


string pattern = @"^([1-9]\\d0,12|0)(\\.\\d0,3)?$";

if ("\\b".Equals(e.KeyChar.ToString()) || "\\r".Equals(e.KeyChar.ToString()) || "\\t".Equals(e.KeyChar.ToString()))

return;


if (!Regex.IsMatch(text, pattern))

e.Handled = true;




/// <summary>
/// 行增加事件===>多级联动 [需要把dataPropetyName值移除]
/// </summary>
/// <param name="sender"></param>
/// <param name="ev"></param>
private void listDataGriddView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs ev)

if (ev.RowIndex == -1 || ev.RowCount == 0 || detailList== null)

return;

//Console.WriteLine("行数:------------" + ev.RowCount);
int maxCount = detailList != null && detailList.Count > ev.RowCount ? detailList.Count : ev.RowCount;
maxCount = ev.RowCount <= 1 ? ev.RowCount : maxCount;
for (int i = 0; i < maxCount; i++)

string packComboboxSql = "select OS_ZB_PURCHASE_PROJECT_INFO.PACK_NO as keyName,OS_ZB_PURCHASE_PROJECT_INFO.PACK_NAME as keyValue from OS_ZB_PURCHASE_PROJECT_INFO where OS_ZB_PURCHASE_PROJECT_INFO.MARK_NO =" + detailList[i].MarkNo + " order by PACK_NAME";

List<ComboBoxVo> packList = SQLiteLibrary.SelectBySql<ComboBoxVo>(sqliteDbLocation, sqliteDbName, packComboboxSql);

DataGridViewColumn column = this.listDataGriddView.Columns["packName"];
if (column is DataGridViewComboBoxColumn)

List<string> pklist = new List<string>();
for (int k = 0; k < packList.Count; k++)

pklist.Add(packList[k].KeyValue);

pklist.Insert(0, "请选择");
DataGridViewComboBoxCell boxCell = new DataGridViewComboBoxCell();
boxCell.Value = detailList.Count <= currentRow ? "" : detailList[currentRow].PackName;
Console.WriteLine("值:" + boxCell.Value);
boxCell.DataSource = pklist;
//分包信息
this.listDataGriddView.Rows[i].Cells["packName"] = boxCell;


/* DataGridView dgv = (DataGridView)sender;
Console.WriteLine("次数:------------"+ currentRow);
currentRow++;
//当前行 不能超过数据的最大行
if (ev.RowIndex < dgv.Rows.Count)

//&& detailList == null
if (dgv.Columns[1].Name == "markNo")

string packComboboxSql = "select OS_ZB_PURCHASE_PROJECT_INFO.PACK_NO as keyName,OS_ZB_PURCHASE_PROJECT_INFO.PACK_NAME as keyValue from OS_ZB_PURCHASE_PROJECT_INFO where OS_ZB_PURCHASE_PROJECT_INFO.MARK_NO =" + detailList[ev.RowIndex].MarkNo + "";

List<ComboBoxVo> packList = SQLiteLibrary.SelectBySql<ComboBoxVo>(sqliteDbLocation, sqliteDbName, packComboboxSql);

DataGridViewColumn column = this.listDataGriddView.Columns[2];
if (column is DataGridViewComboBoxColumn)

List<string> pklist = new List<string>();
for (int i = 0; i < packList.Count; i++)

pklist.Add(packList[i].KeyValue);

pklist.Insert(0, "请选择");
DataGridViewComboBoxCell boxCell = new DataGridViewComboBoxCell();
boxCell.Value = detailList.Count <= currentRow ? "" : detailList[currentRow].PackName;
Console.WriteLine("值:" + boxCell.Value);
boxCell.DataSource = pklist;
//分包信息
boxCell.Value = detailList[ev.RowIndex].PackName;
this.listDataGriddView.Rows[ev.RowIndex].Cells[2] = boxCell;
//detailList[ev.RowIndex].PackName;
//currentRow++;


*/


/// <summary>
/// 单元格验证
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listDataGriddView_CellValidated(object sender, DataGridViewCellEventArgs e)

DataGridViewColumn currentColum = this.listDataGriddView.Columns[e.ColumnIndex];
string columName= currentColum.Name;

if("depositMoney".Equals(columName) || "depositInsure".Equals(columName) || "totalMoney".Equals(columName) )

var value = this.listDataGriddView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if(value!=null && value.ToString().EndsWith("."))

this.listDataGriddView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = value.ToString().Substring(0, value.ToString().Length - 1);






/// <summary>
/// 图片上传
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)

UploadForm upload = new UploadForm(GetSelectType(), "文件|*.jpg;*.png;*bpm,*pdf;*PDF");
DialogUtil.ShowDialog(upload, this, 800, 500, new FormWindowProp(false, false, FormBorderStyle.FixedSingle));


/// <summary>
/// 下拉框信息[原经营异常名录==》变为企业信用查询报告 严重违法企业名单==》该类型删除]
/// </summary>
/// <returns></returns>
private List<ComboBoxVo> GetSelectType()

List<ComboBoxVo> list = new List<ComboBoxVo>();
ComboBoxVo v0 = new ComboBoxVo("请选择", "");
ComboBoxVo v1 = new ComboBoxVo("保单", "baodan", "文件|" + ConstantVo.FILE_TYPE_IMAGE_2);
ComboBoxVo v3 = new ComboBoxVo("汇款", "huikuan", "文件|" + ConstantVo.FILE_TYPE_IMAGE_2);
list.Add(v0);
list.Add(v1);
list.Add(v3);
return list;



/// <summary>
///
/// </summary>
/// <param name="fileInfoList"></param>
/// <param name="childCallBack">子页面回调方法</param>
/// <returns></returns>
public R CallBackUpload(List<FileInfoVo> fileInfoList, Action childCallBack)

R resultR = new R();
try

//上传完了写入数据库
FileInfoVo fileInfoVo = fileInfoList[0];

currentDeposit.AttachId = fileInfoVo.EnclosureId;//附件id
currentDeposit.VoucherCategory = fileInfoVo.AttachType;

SysFileInfo sysFile = new SysFileInfo();
util.ObjectUtil.CopyPop(fileInfoVo, ref sysFile);
sysFile.Id = fileInfoVo.EnclosureId;


//单纯的数据存储
resultR = WebRequestUtil.PostBasicEntityDataApi(apiUpdateFile, currentDeposit);
if (!resultR.Successful)

MessageBox.Show(resultR.ResultHint, "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
return resultR;


//附件信息
SQLiteLibrary.insertData(sqliteDbLocation, sqliteDbName, SQLiteSqlUtils.CreateInsertSql(sysFile));

SQLiteLibrary.ExcuteSql(SQLiteSqlUtils.CreateUpdateSql(currentDeposit,new string[] "id"));

resultR.Successful = true;

//重新加载数据
LoadData(null);


catch (Exception ex)

MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return resultR;

finally
return resultR;




/// <summary>
/// 缴纳方式 选中改变触发事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)

ComboBox comboBox =(ComboBox)sender;
this.sfanjn.Enabled = comboBox.SelectedItem.ToString() == "投保";

if(this.listDataGriddView.DataSource is List<OsZbSupplierDepositDetail>)

this.listDataGriddView.DataSource = detailList;



else

this.listDataGriddView.Rows.Clear();
this.listDataGriddView.DataSource = detailList;




//comboBox.SelectedItem.ToString() == "电汇"
if (!this.sfanjn.Enabled)

this.sfanjn.Checked = false;

this.yxq.Enabled = false;
this.totalInsure.Text = "";
this.totalInsure.ReadOnly = true;

this.totalMoney2.Text = "";
this.totalMoney2.ReadOnly = true;

this.bdh.Text = "";
this.bdh.ReadOnly = true;

this.listDataGriddView.Columns["depositInsure"].Visible = true;
this.listDataGriddView.Columns["totalMoney"].Visible = true;
this.listDataGriddView.Columns["depositMoney"].HeaderText = "总额-汇款(元)";



if(comboBox.SelectedItem.ToString() == "电汇")

this.listDataGriddView.Columns["depositMoney"].HeaderText = "总额(元)";
this.listDataGriddView.Columns["depositInsure"].Visible = false;
this.listDataGriddView.Columns["totalMoney"].Visible = false;



private void dateTimePicker1_ValueChanged(object sender, EventArgs e)




private void groupBox1_Enter(object sender, EventArgs e)




/// <summary>
/// 是否按年缴纳
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sfanjn_CheckedChanged(object sender, EventArgs e)

CheckBox checkBox = (CheckBox)sender;

if(checkBox.Checked && this.payWay.Text == "投保")

this.yxq.Enabled = true;
this.totalInsure.ReadOnly = false;
this.totalMoney2.ReadOnly = false;
this.bdh.ReadOnly = false;

this.AddRowBtn.Visible = false;
this.btnAllCheck.Visible = false;
this.btnDelete.Visible = false;

if (this.listDataGriddView.DataSource is List<OsZbSupplierDepositDetail>)

this.listDataGriddView.DataSource = null;

else

this.listDataGriddView.Rows.Clear();
this.listDataGriddView.DataSource = null;


/*this.listDataGriddView.Rows.Clear();
this.listDataGriddView.DataSource = null;*/

else

this.yxq.Enabled = false;
this.totalInsure.Text = "";
this.totalInsure.ReadOnly = true;

this.totalMoney2.Text = "";
this.totalMoney2.ReadOnly = true;

this.bdh.Text = "";
this.bdh.ReadOnly = true;

this.AddRowBtn.Visible = true;
this.btnAllCheck.Visible = true;
this.btnDelete.Visible = true;




private void DatePickChange(object sender, EventArgs e)

DateTimePicker timePicker = (DateTimePicker)sender;
timePicker.CustomFormat = "yyyy-MM-dd";


private void totalMoney2_TextChanged(object sender, EventArgs e)




private void listDataGriddView_CellClick(object sender, DataGridViewCellEventArgs e)

if(e.RowIndex <0 && e.ColumnIndex < 0)

return;



/* /// <summary>
/// 移除控件 某个注册事件
/// </summary>
public void RemoveEvent(object eventObj)

KeyPressEventHandler keyPressEventHand = null;
EventHandler eventHand = null;
Delegate[] dels = null;

if (eventObj is KeyPressEventHandler)

keyPressEventHand = (KeyPressEventHandler)eventObj;
dels = keyPressEventHand.GetInvocationList();

else if (eventObj is EventHandler)

eventHand = (EventHandler)eventObj;
dels = eventHand.GetInvocationList();


foreach (Delegate d in dels)

//得到方法名
object delObj = d.GetType().GetProperty("Method").GetValue(d, null);
string funcName = (string)delObj.GetType().GetProperty("Name").GetValue(delObj, null);
if (keyPressEventHand != null)

keyPressEventHand -= d as KeyPressEventHandler;

if (eventHand != null)

eventHand -= d as EventHandler;


*/




核心代码分为四块:

1.加载数据 函数为 LoadData

c#

2.点击新增行事件 函数为 AddRowBtn_Click

c#

3.行新增事件【被动触发】 函数为 listDataGriddView_RowsAdded

c#

4.单元格修改完毕事件 函数为listDataGriddView_CellEndEdit

c#

采坑1、数据绑定

listDataGriddView 是table的组件的name

this.listDataGriddView.DataSource 我选择的是集合, 已开始从数据库取出来空。只有这样的代码 this.listDataGriddView.DataSource = detailList; 如果detailList 是null 新增就能只能this.listDataGriddView.Rows.Add() 这个方法来新增行, 因为已开始的数据绑定就是个空 ,导致后面的新增 和删除 都要做判断 使用数据绑定和Rows 来新增和删除 【真的很麻烦】

c#

这个因为如果绑定数据源【list】是不为null但长度是0的 ,一旦点击新增 后 点击行就会抛出 索引为-1的相关错误。这个微软不知道咋设计的。

采坑2、行事件触发bug

listDataGriddView_RowsAdded 的行新增触发的对象 有时候跟行数没有关系 感觉是内部机制的问题

所以: int maxCount = detailList != null && detailList.Count > ev.RowCount ? detailList.Count : ev.RowCount; maxCount = ev.RowCount <= 1 ? ev.RowCount : maxCount;

这样才能防止集合越界。

采坑3、新增行和删除行的完善

以上是关于c# 之winform 可编辑table 踩过的坑的主要内容,如果未能解决你的问题,请参考以下文章

总结之踩过的后台服务报500的坑

iOS踩过的坑之一个Controller中放两个collectionView

iOS踩过的坑之列表刷新图片闪烁问题

python易错盲点排查之+=与+的区别分析以及一些赋值运算踩过的坑

ng-zorro-antd中踩过的坑

那些年踩过的坑(持续更新)