1. 程式人生 > >玩轉控制元件:對Dev中GridControl控制元件的封裝和擴充套件

玩轉控制元件:對Dev中GridControl控制元件的封裝和擴充套件

    又是一年清明節至,細雨綿綿猶如淚光,樹葉隨風擺動....

        轉眼間,一年又過去了三分之一,疫情的嚴峻讓不少企業就跟清明時節的樹葉一樣,搖搖欲墜。裁員的裁員,降薪的降薪,996的996~~說起來都是淚,以上種種竟然在本公司都能見到,然而你現在還能看到博主翹著二郎腿,在工位上信誓旦旦的敲著程式碼也是奇蹟!哎,生活不易,且行且珍惜吧!

  Talk is Cheap, Show me the code!

  如上所說,雖環境如此嚴峻,但也不能生疏了咱吃飯的手藝。不禁讓我感受到,對技術的追求,不僅僅靠的是興趣,更重要的是堅持啊!

  廢話少說,前面幾個環節,博主分享了對基礎控制元件的封裝和擴充套件(舉了幾個栗子,大家可以舉一反三。或者公眾號Call我,原始碼免費奉上。),後面和大家一起看看對容器控制元件的封裝和擴充套件,本篇以常用的Dev中GridControl控制元件的封裝和擴充套件。

  對容器控制元件的封裝和擴充套件,和其他控制元件一樣。首先,新建一個自定義類,讓其繼承Dev的GridControl:

 public class KzxGridControl : GridControl, IControl

    其次,給需要擴充套件的屬性用特性方式標識,便於在VS設計介面來控制。本篇以最常用的兩個功能來進行解析——GridControl右鍵選單之複製行和匯出Excel.具體核心程式碼如下:

private bool _displayRightClickCopyMenu = true;
private bool _displayRightClickExportExcel = true;
/// <summary>
/// 是否顯示右鍵選單的複製行
/// </summary>
[Category("右鍵選單"), Description("DisplayRightClickMenu,顯示右鍵選單的複製行按鈕"), Browsable(true)]
public bool DisplayRightClickMenu
{
    get { return _displayRightClickCopyMenu; }
    set { _displayRightClickCopyMenu = value; }
}
/// <summary>
/// 是否顯示右鍵選單的匯出Excel
/// </summary>
[Category("右鍵選單"), Description("DisplayRightExportExcel,顯示右鍵選單的匯出Excel按鈕"), Browsable(true)]
public bool DisplayRightExportExcel
{
    get { return _displayRightClickExportExcel; }
    set { _displayRightClickExportExcel = value; }
}

   編譯後,返回設計介面,點選GridControl控制元件檢視屬性窗體會發現我們剛剛新增的擴充套件屬性:

   屬性設定完畢後,接下來就是初始化繫結該選單的功能事件。

/// <summary>
/// 構造
/// </summary>
public KzxGridControl()
    : base()
{
    if (this.MainView == null)
    {
        this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView();
        ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit();
        ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
        this.SuspendLayout();
        this.gridView1.GridControl = this;
        this.gridView1.Name = "gridView1";
        this.gridView1.VertScrollVisibility = ScrollVisibility.Always;
        this.gridView1.HorzScrollVisibility = ScrollVisibility.Always;
        this.MainView = this.gridView1;
        this.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] {
    this.gridView1});
        ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit();
        ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
        this.ResumeLayout(false);
    }

    this._KzxBandedGridView = new KzxBandedGridView(false, _bandedGridView, this);
    this.Load += new EventHandler(GridControl_Load);
}

  建構函式中,繫結load事件,用於觸發選單事件

        
private void GridControl_Load(object sender, EventArgs e)
{ 
    ToolStripItem item3;
    ToolStripItem item4; 

    if (this.ContextMenuStrip == null)
    {
        this.ContextMenuStrip = new ContextMenuStrip();
    }
    this._ContextMenuStrip = this.ContextMenuStrip;
    _ContextMenuStrip.Opened += _ContextMenuStrip_Opened;
    //如果需要顯示右鍵複製行
    if (_displayRightClickCopyMenu)
    {
        item3 = this._ContextMenuStrip.Items.Add(GetLanguage("RMI000452", "複製行"));//複製行
        item3.Name = "copyline";
        item3.Click += new EventHandler(CopyLine);
    }
    //如果需要顯示右鍵匯出Excel
    if (_displayRightClickExportExcel)
    {
        item4 = this._ContextMenuStrip.Items.Add(GetLanguage("SYS001196", "匯出EXCEL"));//匯出EXCEL
        item4.Click += new EventHandler((s, ee) =>
        { 
            //TODO:匯出Excel動作
        });
    }
    ...

  匯出方法比比皆是,因專案而異,多表頭的,普通的。。就不獻醜了(如有需要也可公眾號call我,原始碼免費奉上)。此處我們拿複製行來舉栗子,方法如下:

#region 複製行 
  public void CopyLine(object sender, EventArgs e)
  {
      StringBuilder sqlsb = new StringBuilder();
      GridView gridview = this.MainView as GridView;
      DataTable dt = null;
      DataColumn[] columns = null;
      //BindingSource bs = null;
      DataRow row = null;
      DataRow rowtemp = null;
      //舉例是拿DataTable做資料來源,所以下面程式碼暫時遮蔽
      //bs = (this.DataSource as BindingSource);
      if (this.DataSource != null)
      {
          if (gridview.FocusedRowHandle >= 0)
          {
              row = gridview.GetDataRow(gridview.FocusedRowHandle);
              dt = ((this.DataSource as DataTable).DefaultView as DataView).Table;
              if (dt.PrimaryKey != null)
              {
                  columns = dt.PrimaryKey;
              }

              DataTable dttemp = dt.Clone();
              rowtemp = dttemp.Rows.Add(row.ItemArray);
              foreach (DataColumn c in columns)
              {
                  rowtemp[c.ColumnName] = Guid.NewGuid();
              }
              //判斷iOrder是否存在,存在則不復制,且取最大值+1
              if (dt.Columns.Contains("iOrder"))
              {
                  int maxIOrder = string.IsNullOrWhiteSpace(dt.Compute("max(iOrder)", "1=1").ToString()) ? 0 : Convert.ToInt32(dt.Compute("max(iOrder)", "1=1").ToString());
                  rowtemp["iOrder"] = maxIOrder + 1;
              }
              dt.ImportRow(rowtemp);

              //執行右鍵複製行委託
              OnRowCopy?.Invoke();
          }
      }
      else
      {
          KzxMessageBox.Show(sysClass.ssLoadMsgOrDefault("MSG002204", "資料來源不能為空"));
      }
  }
  #endregion
private void CopyLineMenu()
  {
      //是否顯示右鍵的複製行按鈕
      if (this._displayRightClickCopyMenu == true)
      {
          bool iscontain = false;
          ToolStripItem item3;
          if (this.ContextMenuStrip == null)
          {
              this.ContextMenuStrip = new ContextMenuStrip();
          }
          this._ContextMenuStrip = this.ContextMenuStrip;
          for (int i = 0; i < this._ContextMenuStrip.Items.Count; i++)
          {
              if (this._ContextMenuStrip.Items[i].Name.Equals("copyline", StringComparison.OrdinalIgnoreCase) == true)
              {
                  iscontain = true;
                  break;
              }
          }
          if (iscontain == false)
          {
              item3 = this._ContextMenuStrip.Items.Add(GetLanguage("RMI000452", "複製行"));//複製行
              item3.Name = "copyline";
              item3.Click += new EventHandler(CopyLine);
          }
      }
  }

  具體效果如下:

   完成!不過注意,以上功能如果運用於實際專案,煩請做好控制,尤其複製行功能,初衷是一個很複雜的GridControl十幾二十多列的,不想一列一列輸入的,可以採用這種模式,複製行後改動下即可。注意最好是在編輯狀態下顯示此操作,否則不僅不會儲存到資料庫,還白費功夫!此本只是演示效果而已!本篇到此結束...

        最後,由於後續所有重寫/重繪控制元件都在同一個專案使用,而且Dev系統引用檔案較多,壓縮後原始碼檔案仍然很大,如果有需要原始碼的朋友,可以微信公眾號聯絡博主,原始碼可以免費贈予~!有疑問的也可以CALL我一起探討。

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