­

玩轉控制項:對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我一起探討。

    最後,感謝您的耐心陪伴!如果覺得本篇博文對您或者身邊朋友有幫助的,麻煩點個關注!贈人玫瑰,手留余香,您的支援就是我寫作最大的動力,感謝您的關注,期待和您一起探討!再會!