前言
今天给了一个新的需求:要在原来只有一页表的基础上,增加另一张表。也就是分页,表里面放数据网格,存放的是数据库的SELECT展示内容,还要支持增删改。还要和之前一个实现方式一样,对分页进行约束,比如未保存无法切换表格。

算是一个全新的需求,之前没接触过WinForm的控件。

结果展示
WinForm实现分页

结果未保存无法切换页面

系统环境
Windows 10 专业版
Visual Studio 2010
C#/.NET 4.0

需求分析
这次的需求并不明确,只是一句话,所以要把需求先确认。

控件理解
开始不清楚控件的含义,经过同事讲解,大概明白属性和事情的意义。这对后面进行分页约束的实现有很大帮助。

具体实现

  • 引入TabControl,添加标签页/选项卡。添加后会在.Designer文件自动生成代码。

  • 在空白处点击,选中标签页/选项卡,右键属性。

  • Name、Text都是标签页/选项卡的属性,都可以修改。修改会直接体现在.Designer文件。

  • 按照自己需要进行修改。

引入DataGridView(DGV),展现数据库内容

  • 找到工具箱

  • 找到DataGridView,添加后也会在.Designer文件自动生成代码

  • 在属性卡里面也可以看到各种信息

在DGV里面展示数据库

_dtOverdueSecuInst = SimpleDal.Query<DataTable>(xQuant.Accounting.Interface.ExternalProvider.ExternalInterface.TRD,
	"SELECT * FROM TTRD_UT_TC_OVERDUE_SECU_INST WHERE 1=1  " + whereIn + " ORDER BY TSK_ID, SET_DATE");

dgvOverDueSecuInst.DataSource = _dtOverdueSecuInst;
dgvOverDueSecuInst.Columns["ID"].ReadOnly = true;
dgvOverDueSecuInst.Columns["ID"].DefaultCellStyle.BackColor = System.Drawing.Color.LightGray;
dgvOverDueSecuInst.Refresh();
  • 代码说明

  • _dtOverdueSecuInst 类型是DataTable,也是WinForm的一个控件,以表格形式存储数据。

  • dgvOverDueSecuInst类型是DataGridView,就是数据网格。

  • 上述代码实现了数据库的SELECT结果通过DataTable,展示到DataGridView上面。

  • 结果如图

到此,展示功能完成
下面实现展示结果的增删改

代码使用了.NET自带的TransactionScope事务函数。具体实现也复杂的,不多写了。
模板参考:https://docs.microsoft.com/zh-cn/dotnet/api/system.transactions.transactionscope?redirectedfrom=MSDN&view=net-5.0

Save保存函数具体实现

private void SaveOverdueSecuInst()
{
	try
	{
		using (TransactionScope trans = new TransactionScope())
		{
			TestCaseOverdueSecuInst tcOverdueSecuInst = new TestCaseOverdueSecuInst();
			foreach (DataRow dr in _dtOverdueSecuInst.GetChanges().Rows)
			{
				if (dr.RowState != DataRowState.Deleted)
				{
					tcOverdueSecuInst.ID = UTUtils.ToInt(dr["ID"].ToString());
				}
				else
				{
					tcOverdueSecuInst.ID = UTUtils.ToInt(dr["ID", DataRowVersion.Original].ToString());
				}
				TestCaseDal4InpuOther.SaveOverdueSecuInst(tcOverdueSecuInst, dr.RowState);
			}
			InitData();
			trans.Complete();
			MessageBox.Show("逾期券指令输入表保存成功", "提示");
		}
	}
	catch (Exception e)
	{
		MessageBox.Show(e.Message.ToString(), "提示");
	}
}
  • 代码说明
  • TestCaseOverdueSecuInst是自己写的类,里面存放ID等属性。
  • DataRowState是C#自带,用于枚举。
  • 上述代码通过switch选择,实现了数据库增(.Added)删(.Deleted)改(.Modified)的。
  • 详细的增删改代码实现,我另外写一个博客,内容很多。

保存按钮调用Save保存函数

private void btnSave_Click(object sender, EventArgs e)
{
	if (this.tabOverDue.SelectedTab == tpOverDueSecuInst)
	{
		SaveOverdueSecuInst();
	}
}
  • 代码说明
  • if判断是判断是否为当前页,只有是当前页才会执行保存。也就是点击保存按钮只进行单张保存,进行页与页的隔离。

对分页进行约束
比如未保存无法切换表格
这是当时实现的一个难点,因为不清楚控件事件的具体实现。在参考相似代码之后,成功实现了。

  • 首先编写has判断函数,判断当前页是否有改动未保存
private bool hasUnSavedChange()
{
	bool isChange = false;
	if (tabOverDue.SelectedTab != null)
		if (_dtOverdueSecuInst != null && _dtOverdueSecuInst.GetChanges() != null)
		isChange = true;                
	}
	return isChange;
}
  • 然后写成控件的内置函数TabControlCancelEventHandler(object sender, TabControlCancelEventArgs e)的参数形式
private void tabOverDue_BeforeSelect(object sender, TabControlCancelEventArgs e)
{
	//打开其他表前判断有无存在未保存数据
	if (hasUnSavedChange())
	{
		MessageBox.Show("存在未保存数据", "提示");
		e.Cancel = true;
		return;
	}
}
  • 最后添加到TabControl的控件代码里面
    this.tabOverDue.Selecting += new System.Windows.Forms.TabControlCancelEventHandler(this.tabOverDue_BeforeSelect);

  • 代码说明

  • tabOverDue是TabControl的名字,Selecting 内置函数来判断是否点击别的表。如果点击就调用tabOverDue_BeforeSelect函数,看全部表是否有未保存数据。

  • TabControlCancelEventHandler是TabControl内置函数,起到监视的目的。这些内置函数都是配套的,包括上面的TabControlCancelEventArgs 类。

  • 只有使用TabControl配套的内置函数才可以实现,不然会发生语法错误。

  • 参考代码的控件是treeViewTable,内置函数和TabControl并不相同。这是实现的一个困难。

后记
从“需求明确” -> “控件学习” -> “控件源码理解” -> “编程实现” -> “不断调试/优化”,是一次新的挑战。成就也已获得。
这次用TabControl控件的内置函数勉强实现原来treeViewTable控件的需求。但是如果需求对扩展性要求再提高,C#估计就无法完成了。
因为所有的内置类/函数,都是封装写好的。你不能去修改任何微软给你的函数,虽然大部分封装函数都很好用。
但是正是这种封闭性,让.NET离时代主流的开源越来越远。不久的将来,我还是会回到Java。

 posted on 2020-12-17 19:29  Basic++  阅读(6428)  评论(0编辑  收藏  举报