玩轉控制項:對Dev的GridControl控制項擴展
- 2020 年 4 月 10 日
- 筆記
緣由
一切實現來源於需求,目的在於不盲目造輪子,有小夥伴兒在看了《玩轉控制項:對Dev中GridControl控制項的封裝和擴展》文章後,私信作者說,因公司業務邏輯比較複雜,展示欄位比較多,尤其網格列表控制項展示數據太多時候,很多關鍵列資訊不同用戶要求展示效果不同,問我有沒有好點的處理方式來滿足不同客戶的需求。
看到這裡作者還是比較暗自竊喜的,畢竟自己造的輪子不止作者一個人在用,而且還能收穫客戶的實際需求來完善輪子。當然客戶需求存在即合理。畢竟There are a thousand Hamlets in a thousand people’s eyes.
何以解憂唯有擼碼
有了需求,眼球一轉,就擼起袖子加油干吧。初步想法直接在《玩轉控制項:對Dev中GridControl控制項的封裝和擴展》的基礎上,右鍵菜單網格設置狀態裡面處理吧。把處理後的結果通過配置文件方式(ini,xml…)存儲起來,網格載入的時候,通過校驗是否存在配置文件來載入不同客戶的配置資訊即可。 有了想法,就行動起來吧!氣運丹田,雙手攤開,紮下馬步,使出”拖控制項大法”一氣呵成!
大致需求與實現如上圖,本來還有列中文列名的,但是客戶說不要~~(如有更多不同需求或更好的想法,請自行添加或者公眾號私信作者一起探討)
Talk is Cheap,Show me the Code
跟用戶反覆溝通,具體效果圖如上,下面一起看看是如何實現的。
思路:網格表格右鍵點擊網格狀態設置,彈出如上設置窗體,窗體介面載入的時候綁定GridControl所有數據列,並在保存時候存儲到配置文件中,具體程式碼如下:
/// <summary> /// 數據載入初始化 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void frm_GridSetting_Load(object sender, EventArgs e) { //讀取配置文件,更新網格狀態 string sPath = $@"{ Application.StartupPath}Task.xml"; DataTable dtColumns = this.gc.DataSource as DataTable; GridView gvv = gc.MainView as GridView; if (dtColumns != null && dtColumns.Rows.Count > 0) { DataTable dtSetting = new DataTable("GridSetting"); dtSetting.Columns.Add("ColumnsName", typeof(String)); dtSetting.Columns.Add("isDisplay", typeof(Boolean)); dtSetting.Columns.Add("Freeze", typeof(String)); dtSetting.Columns.Add("ColumnsWidth", typeof(Int32)); dtSetting.Columns.Add("Order1", typeof(String)); dtSetting.Columns.Add("Order2", typeof(String)); dtSetting.Columns.Add("Top", typeof(String)); dtSetting.Columns.Add("Button", typeof(String)); dtSetting.Columns.Add("iOrder", typeof(Int32)); if (!File.Exists(sPath)) { for (int i = 0; i < gvv.VisibleColumns.Count; i++) { string colName = gvv.VisibleColumns[i].Name.Replace("col", ""); dtSetting.Rows.Add(new object[] { colName, true, "無", 120, "上移", "下移", "置頂", "置底", gvv.VisibleColumns[i].VisibleIndex }); } } else { //讀取XML 綁定數據源 XDocument xdoc = XDocument.Load(sPath); var query = from a in xdoc.Descendants("Columns") select new { ColumnsName = a.Attribute("ColumnsName").Value, isDisplay = a.Element("isDisplay").Value, Freeze = a.Element("Freeze").Value, ColumnsWidth = a.Element("ColumnsWidth").Value, iOrder = a.Element("iOrder").Value }; int index = 0; foreach (var item in query.ToList()) { dtSetting.Rows.Add(new object[] { item.ColumnsName, Boolean.Parse(item.isDisplay), item.Freeze, int.Parse(item.ColumnsWidth), "上移", "下移", "置頂", "置底", index }); index++;//排序重置 } } gcSetting.DataSource = dtSetting; repositoryItemButtonEdit1.ButtonClick += RepositoryItemButtonEdit1_ButtonClick;//上移 repositoryItemButtonEdit2.ButtonClick += RepositoryItemButtonEdit2_ButtonClick;//下移 repositoryItemButtonEdit3.ButtonClick += RepositoryItemButtonEdit3_ButtonClick;//置頂 repositoryItemButtonEdit4.ButtonClick += RepositoryItemButtonEdit4_ButtonClick;//置底 } }
網格窗體點擊確認,用來保存用戶的配置資訊:
/// <summary> /// 確定 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSure_Click(object sender, EventArgs e) { try { //保存動作 string sPath = $@"{ Application.StartupPath}Task.xml"; loop: if (!File.Exists(sPath)) { File.Create(sPath).Close(); XDocument xdoc = new XDocument(); //創建跟節點 XElement root = new XElement("Mes"); //添加跟節點 xdoc.Add(root); DataTable dtSetting = gcSetting.DataSource as DataTable; int index = 0; foreach (DataRow item in dtSetting.Rows) { //創建person節點 XElement per = new XElement("Columns"); //添加person節點 root.Add(per); //創建屬性節點 XAttribute ColumnsName = new XAttribute("ColumnsName", item["ColumnsName"].ToString()); //name節點 XElement isDisplay = new XElement("isDisplay", item["isDisplay"].ToString()); XElement Freeze = new XElement("Freeze", item["Freeze"].ToString()); XElement ColumnsWidth = new XElement("ColumnsWidth", item["ColumnsWidth"].ToString()); XElement iOrder = new XElement("iOrder", index); //對person節點添加id屬性 以及name sex age節點 per.Add(ColumnsName, isDisplay, Freeze, ColumnsWidth, iOrder); index++; } //保存linq to xml 文件 xdoc.Save(sPath); } else { File.Delete(sPath); goto loop; } //刷新原始介面顯示 if (RefreshMDIFormEvent != null) { RefreshMDIFormEvent(); } } catch (Exception ex) { } finally { this.Close(); } }
因最近項目上線,時間緊迫(吃飯時間寫的部落格)。作者就偷個懶,每次確認都會先刪除配置文件,然後重新新增。實際項目中可以通過更新來處理。而且goto語法也比較low,大家將就著看下效果,具體更好實現,夥伴們可以自行重寫。唯一值得注意的點是File文件流的問題,此處偷懶寫法
File.Create(sPath).Close();
防止保存配置文件的時候,提示文件被其他用戶佔用的問題。至於上移,下移,置頂,置底等功能網上很多示例,也可以公眾號私聊作者,所有源碼免費贈送。配置文件如圖:
配置介面梳理完畢,只需要在主窗體數據載入後,讀取配置文件資訊變更即可:
kzxGridControl1.DataSource = dataTable; GridView gv = this.kzxGridControl1.MainView as GridView; //讀取配置文件,更新網格狀態 string sPath = $@"{ Application.StartupPath}Task.xml"; if (File.Exists(sPath)) { XDocument xdoc = XDocument.Load(sPath); for (int i = 0; i < gv.Columns.Count; i++) { string colName = gv.Columns[i].Name.Replace("col", ""); var query = (from a in xdoc.Descendants("Columns") where a.Attribute("ColumnsName").Value == colName select new { isDisplay = a.Element("isDisplay").Value, Freeze = a.Element("Freeze").Value, ColumnsWidth = a.Element("ColumnsWidth").Value, iOrder = a.Element("iOrder").Value }).FirstOrDefault(); if (query != null) { gv.Columns[i].Visible = Boolean.Parse(query.isDisplay); if (query.Freeze.ToLower().Equals("無")) { gv.Columns[i].Fixed = FixedStyle.None; } else if (query.Freeze.ToLower().Equals("左邊")) { gv.Columns[i].Fixed = FixedStyle.Left; } else if (query.Freeze.ToLower().Equals("右邊")) { gv.Columns[i].Fixed = FixedStyle.Right; } if (!Boolean.Parse(query.isDisplay)) { gv.Columns[i].VisibleIndex = -1; gv.Columns[i].Visible = Boolean.Parse(query.isDisplay); } else { gv.Columns[i].VisibleIndex = int.Parse(query.iOrder); } gv.Columns[i].Width = int.Parse(query.ColumnsWidth); } } }
為了能實時更新配置效果,可在配置窗體添加個委託用於刷新主介面數據:
public delegate void RefreshMDIFormHandler();
public event RefreshMDIFormHandler RefreshMDIFormEvent;
/// <summary> /// 網格狀態設置 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void kzxSimpleButton2_Click(object sender, EventArgs e) { frm_GridSetting frm = new frm_GridSetting(kzxGridControl1); frm.RefreshMDIFormEvent += Frm_RefreshMDIFormEvent; frm.ShowDialog(); } private void Frm_RefreshMDIFormEvent() { this.frm_ShowControl_Load(null, null); }
時間緊急,處理的比較粗糙,直接調用load重新載入了。
完成!所有實現處理完成,來一起看看效果:
(原圖效果)
(Telephone列上移下移確定後效果)
(Email列置頂效果)
(隱藏列效果)
(列寬設置效果)
(motto左凍結效果)
(右凍結效果)
為了後續其他控制項載入問題,本篇用按鈕方式實現的彈窗,有需求的夥伴們可以把相關程式碼移動到GridContrl用戶控制項的右鍵菜單中實現。此處不在過多闡述。謝謝螢幕前您的耐心陪伴!
結束語
由於後續所有重寫/重繪控制項都在同一個項目使用,而且Dev系統引用文件較多,壓縮後源碼文件仍然很大,如果有需要源碼的朋友,可以微信公眾號聯繫部落客,源碼可以免費贈予~!有疑問的也可以CALL我一起探討。
最後,感謝您的耐心陪伴!如果覺得本篇博文對您或者身邊朋友有幫助的,麻煩點個關注!贈人玫瑰,手留余香,您的支援就是我寫作最大的動力,感謝您的關注,期待和您一起探討!再會!