Winform界面中主從表編輯界面的快速處理

来源:http://www.cnblogs.com/wuhuacong/archive/2017/11/20/7865083.html
-Advertisement-
Play Games

在Winform開發中,我們往往除了常規的單表信息錄入外,有時候設計到多個主從表的數據顯示、編輯等界面,單表的信息一般就是控制項和對象實體一一對應,然後調用API保存即可,主從表就需要另外特殊處理,本隨筆介紹如何快速實現主從表編輯界面的處理,結合GridControl控制項的GridView控制項對象,實... ...


在Winform開發中,我們往往除了常規的單表信息錄入外,有時候設計到多個主從表的數據顯示、編輯等界面,單表的信息一般就是控制項和對象實體一一對應,然後調用API保存即可,主從表就需要另外特殊處理,本隨筆介紹如何快速實現主從表編輯界面的處理,結合GridControl控制項的GridView控制項對象,實現數據在列表中的實時編輯,非常方便。

1、主從表的界面設計及展示

主從表一般涉及兩個以上的表,一個是主表,其他的是從表的,在實際情況下,一般包含兩個表較多,我們這裡以兩個表的主從表關係進行分析處理。

例如我們建立兩個報銷申請單表關係如下所示。

對於報銷的主從表信息,我們可以在列表中進行展示,如下界面所示,分為兩部分:一部分是主表信息,一部分是從表信息,單擊主表信息後,顯示對應從表的列表信息。

那麼我們新增一條主表記錄的時候,那麼可以彈出一個新的界面進行數據的維護處理,方便我們錄入主從表的信息,界面如下所示。

上面界麵包括了主表信息,以及從表的信息(在GridView中實時錄入)兩部分,這樣填寫後統一進行提交處理。

 

2、主從表編輯界面的處理

這裡主要介紹一下主從表的編輯界面處理,也就是上面這個界面的實現處理。

其中初始化GridView的代碼如下所示。

        /// <summary>
        /// 初始化明細表的GridView數據顯示
        /// </summary>
        private void InitDetailGrid()
        {
            //初始清空列
            this.gridView1.Columns.Clear();
            //設置部分列隱藏
            this.gridView1.CreateColumn("ID", "編號").Visible = false;
            this.gridView1.CreateColumn("Header_ID", "主表編號").Visible = false;
            this.gridView1.CreateColumn("Apply_ID", "申請單編號").Visible = false;
            //添加下拉列表列,並綁定數據源
            this.gridView1.CreateColumn("FeeType", "費用類型", 100).CreateComboBox().BindDictItems("費用類型");
            //創建日期列並指定格式
            var OccurTime = this.gridView1.CreateColumn("OccurTime", "發生時間", 120).CreateDateEdit();
            OccurTime.EditMask = "yyyy-MM-dd HH:mm";
            OccurTime.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm";
            //創建數值列
            this.gridView1.CreateColumn("FeeAmount", "費用金額").CreateSpinEdit();
            //創建備註列
            this.gridView1.CreateColumn("FeeDescription", "費用說明", 200).CreateMemoEdit();

            //初始化GridView,可以新增列
            this.gridView1.InitGridView(GridType.NewItem, false, EditorShowMode.MouseDownFocused, "");
            //轉義列內容顯示
            this.gridView1.CustomColumnDisplayText += new CustomColumnDisplayTextEventHandler(gridView1_CustomColumnDisplayText);
            //處理單元格的樣式
            this.gridView1.RowCellStyle += new RowCellStyleEventHandler(gridView1_RowCellStyle);
            //不允許頭部排序
            this.gridView1.OptionsCustomization.AllowSort = false;
            //繪製序號
            this.gridView1.CustomDrawRowIndicator += (s, e) =>
            {
                if (e.Info.IsRowIndicator && e.RowHandle >= 0)
                {
                    e.Info.DisplayText = (e.RowHandle + 1).ToString();
                }
            };

            //對輸入單元格進行非空校驗
            this.gridView1.ValidateRow += delegate(object sender, ValidateRowEventArgs e)
            {
                var result = gridControl1.ValidateRowNull(e, new string[]
                {
                    "FeeType"
                });
            };
            //新增行的內容初始化
            this.gridView1.InitNewRow += (s, e) =>
            {
                gridView1.SetRowCellValue(e.RowHandle, "ID", Guid.NewGuid().ToString());
                gridView1.SetRowCellValue(e.RowHandle, "Header_ID", tempInfo.ID);
                gridView1.SetRowCellValue(e.RowHandle, "Apply_ID", tempInfo.Apply_ID);
                gridView1.SetRowCellValue(e.RowHandle, "OccurTime", DateTime.Now);
            };
        }

        void gridView1_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)
        {
            GridView gridView = this.gridView1;
            if (e.Column.FieldName == "FeeAmount")
            {
                e.Appearance.BackColor = Color.Green;
                e.Appearance.BackColor2 = Color.LightCyan;
            }
        }
        void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
        {
            string columnName = e.Column.FieldName;

            if (e.Column.ColumnType == typeof(DateTime))
            {
                if (e.Value != null)
                {
                    if (e.Value == DBNull.Value || Convert.ToDateTime(e.Value) <= Convert.ToDateTime("1900-1-1"))
                    {
                        e.DisplayText = "";
                    }
                    else
                    {
                        e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm");//yyyy-MM-dd
                    }
                }
            }
        }

上面代碼都有詳細的備註,主要就是我們根據資料庫表的關係,創建對應顯示的欄位即可,其中有需要隱藏的那麼就不要顯示(方便獲取對應的值)

            //設置部分列隱藏
            this.gridView1.CreateColumn("ID", "編號").Visible = false;
            this.gridView1.CreateColumn("Header_ID", "主表編號").Visible = false;
            this.gridView1.CreateColumn("Apply_ID", "申請單編號").Visible = false;

如果需要綁定下拉列表類似的欄位,那麼創建對應的數據類型,然後調用綁定函數綁定即可,如下麵代碼

            //添加下拉列表列,並綁定數據源
            this.gridView1.CreateColumn("FeeType", "費用類型", 100).CreateComboBox().BindDictItems("費用類型");

如果是一些特殊的輸入需要設置格式顯示或者掩碼,那麼如下所示

            //創建日期列並指定格式
            var OccurTime = this.gridView1.CreateColumn("OccurTime", "發生時間", 120).CreateDateEdit();
            OccurTime.EditMask = "yyyy-MM-dd HH:mm";
            OccurTime.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm";

另外有一個值得註意的就是我們新增一行從表記錄的時候,需要記錄一些主表的屬性,這樣的話,我們就是在行初始化的時候,賦值給從表的隱藏列即可。

            //新增行的內容初始化
            this.gridView1.InitNewRow += (s, e) =>
            {
                gridView1.SetRowCellValue(e.RowHandle, "ID", Guid.NewGuid().ToString());
                gridView1.SetRowCellValue(e.RowHandle, "Header_ID", tempInfo.ID);
                gridView1.SetRowCellValue(e.RowHandle, "Apply_ID", tempInfo.Apply_ID);
                gridView1.SetRowCellValue(e.RowHandle, "OccurTime", DateTime.Now);
            };

在界面中如果我們需要顯示主表的信息,那麼就根據條件獲取對應的主表記錄對象,然後顯示給界面控制項即可。

        /// <summary>
        /// 顯示常規的對象內容
        /// </summary>
        /// <param name="info"></param>
        private void DisplayInfo(ReimbursementInfo info)
        {
            tempInfo = info;//重新給臨時對象賦值,使之指向存在的記錄對象

            txtCategory.Text = info.Category;
            txtReason.Text = info.Reason;
            txtTotalAmount.Value = info.TotalAmount;
            txtNote.Text = info.Note;
        }

而保存的時候,我們把界面內容重新賦值給對應的主表對象。

        /// <summary>
        /// 編輯或者保存狀態下取值函數
        /// </summary>
        /// <param name="info"></param>
        private void SetInfo(ReimbursementInfo info)
        {
            info.Category = txtCategory.Text;
            info.Reason = txtReason.Text;
            info.TotalAmount = txtTotalAmount.Value;
            info.Note = txtNote.Text;

            info.ApplyDate = DateTime.Now;
            info.ApplyDept = base.LoginUserInfo.DeptId;
            info.CurrentLoginUserId = base.LoginUserInfo.ID;
        }

而我們需要獲取GridView明細輸入的時候,就通過一個函數遍歷獲取GridView的行記錄,轉換為相應的對象即可,如下所示。

        /// <summary>
        /// 獲取明細列表
        /// </summary>
        /// <returns></returns>
        private List<ReimbursementDetailInfo> GetDetailList()
        {
            var list = new List<ReimbursementDetailInfo>();
            for (int i = 0; i < this.gridView1.RowCount; i++)
            {
                var detailInfo = gridView1.GetRow(i) as ReimbursementDetailInfo;
                if (detailInfo != null)
                {
                    list.Add(detailInfo);
                }
            }
            return list;
        }

這樣處理完這些信息後,我們就可以在主表保存的時候,同時保存明細表信息即可。

        /// <summary>
        /// 新增狀態下的數據保存
        /// </summary>
        /// <returns></returns>
        public override bool SaveAddNew()
        {
            ReimbursementInfo info = tempInfo;//必須使用存在的局部變數,因為部分信息可能被附件使用
            SetInfo(info);
            info.Creator = base.LoginUserInfo.ID;
            info.CreateTime = DateTime.Now;

            try
            {
                #region 新增數據

                bool succeed = BLLFactory<Reimbursement>.Instance.Insert(info);
                if (succeed)
                {
                    //可添加其他關聯操作
                    var list = GetDetailList();
                    foreach(var detailInfo in list)
                    {
                        BLLFactory<ReimbursementDetail>.Instance.InsertUpdate(detailInfo, detailInfo.ID);
                    }
                    
                    return true;
                }
                #endregion
            }
            catch (Exception ex)
            {
                LogTextHelper.Error(ex);
                MessageDxUtil.ShowError(ex.Message);
            }
            return false;
        }

其中代碼

BLLFactory<ReimbursementDetail>.Instance.InsertUpdate(detailInfo, detailInfo.ID);

可以對新增記錄保存,也可以對存在的記錄進行更新。

通過上面的介紹,我們可以看到不同的主從表其實邏輯還是很通用的,我們可以把它們的邏輯抽取出來,通過代碼生成工具進行快速生成即可。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 返回總目錄 本小節目錄 Replace Method with Method Object(以函數對象取代函數) Substitute Algorithm(替換演算法) 階段性小結 Substitute Algorithm(替換演算法) 8 Replace Method with Method Obje ...
  • 回到目錄 在進行.net core平臺之後,我們如果希望在請求過程中添加一些事件是非常容易的,你可以把這些事件做成一個中間件Middleware,然後這些中間件就會以Http pipeline的管道方式進行相應,並且它們就像是一個職責鏈,從你定義的第一個中間件開始,一個一個向下傳遞,直到最後一個中間 ...
  • Nginx是個輕量級的反向代理,當然,也有相應的SSL身份認證。本文主要採用一種自我寄宿的方式,使用Nginx集群,通過windows證書(X.509證書),講述客戶端如何訪問伺服器的方法。客戶端以BasicHttpBinding進行訪問Nginx,然後Nginx進行負載均衡,將消息分發到後端任意一... ...
  • 1,菜單。在最新的abp3.1.2中 菜單欄是在左側的如下圖(上中下的結構),中間部分就是我們要添加菜單的地方。 ABP集成了通用的創建和顯示菜單的方式,在展示層web下的appstart文件夾下找到AbpNavigationProvider 添加如下代碼即可 關於菜單部分的具體實現原理,可以在ht ...
  • 1 軟體度量值指標 1.1 可維護性指數 表示源代碼的可維護性,數值越高可維護性越好。該值介於0到100之間。綠色評級在20到100之間,表明該代碼具有高度的可維護性;黃色評級在10到19之間,表示該代碼適度可維護;紅色評級在0至9之間,表示低可維護性。 1.2 圈複雜度 它是通過計算程式流中不同代 ...
  • 當我們使用QQ的時候就會發現,他可以啟動多個QQ,但是有時候,我們不想這樣做,這時候我們就需要使用到單例模式. 1.將Form2的構造函數轉為私有 using System.Windows.Forms; namespace 單例模式 { public partial class Form2 : Fo ...
  • 演示產品下載地址:http://www.jinhusns.com ...
  • 下載地址:http://ilspy.net/ 中文版下載地址:http://www.fishlee.net/soft/ilspy_chs 對dll和exe文件反編譯: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...