【C#/WinForm】TabControl中添加TabPage,並對TabPage進行控制


前言
今天給了一個新的需求:要在原來只有一頁表的基礎上,增加另一張表。也就是分頁,表里面放數據網格,存放的是數據庫的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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM