1. 程式人生 > >玩轉控制元件:擴充套件Dev中SimpleButton

玩轉控制元件:擴充套件Dev中SimpleButton

    何為擴充套件,顧名思義,就是在原有控制元件屬性、事件的基礎上拓展自己需要或實用的屬性、事件等等。或者可以理解為,現有的控制元件已經不能完全滿足我(的需求)了。好的擴充套件會使控制元件更加完善,實用,好用。不好的擴充套件,說白了就是畫蛇添足!好了,跟著博主一起玩轉控制元件吧,看看您在實際專案運用中是否也曾幾何時遇到過這樣的困惑。

        本篇拿一個簡單的Dev控制元件為例,件如其名——SimpleButton,一個成熟的軟體,一定會考慮到所有人的操作習慣以及簡潔舒適的介面。做人如是,控制元件如是。

        本篇緣起於博主最近削尖腦袋,硬著頭皮看英文文件。那傢伙把我讀的,那場面,那氣勢,真是鑼鼓喧天鞭炮起,紅旗招展,文山文海... 大部分它認識我,我不認識它。最後還得靠多年醞釀的Google大法才能撥開雲霧見青天。偶然間聯想到最近預熱的《手撕ERP》(FuckingERP)之控制元件系列,公眾號私信裡面有很多國外的朋友,拿到原始碼,信誓旦旦的按下F5傻眼了。全是中文字,而且有的還亂碼。

   因此,鑑於此,從本篇起,後續所有控制元件系列都會擴充套件一個多語言的屬性功能(俗稱國際化)。多語言功能有很多實現方式,博主之前也實踐過很多方式,比如資原始檔處理、展示介面前呼叫Google翻譯後賦值等等,這些方式有利有弊,本篇博主將採用另外一種方式來實現多語言-資料庫儲存,鍵值對取值的方式。巴拉巴拉巴拉.....

 

        扯遠了扯遠了,迴歸主題,還是來看看博主是怎麼擴充套件按鈕的吧!

        Talk is Cheap,Show me the Code!

        首先,新建一個使用者控制元件,並讓其繼承Dev原始控制元件SimpleButton

public partial class KzxSimpleButton : SimpleButton, ILayoutControl

    後面的ILayoutControl介面,是我用來定義要實現的屬性和事件的,部分程式碼如下:

/// <summary>
/// 沒有多語言的情況下的預設顯示標題
/// </summary>
string DesigeCaption { get; set; }
/// <summary>
/// 設計時的可用性
/// </summary>
bool DesigeEnabled { get; set; }
/// <summary>
/// 設計時可見性
/// </summary>
bool DesigeVisible { get; set; }
/// <summary>
/// 控制元件的唯一標識
/// </summary>
string Key { get; set; }
/// <summary>
/// 佈局列號
/// </summary>
int LayoutColumn { get; set; }
/// <summary>
/// 佈局跨的列數
/// </summary>
int LayoutColumnSpan { get; set; }
/// <summary>
/// 佈局行號
/// </summary>
int LayoutRow { get; set; }
/// <summary>
/// 佈局跨的行數
/// </summary>
int LayoutRowSpan { get; set; }
/// <summary>
/// 多語言環境下顯示文字的對應標識
/// </summary>
string MessageCode { get; set; }

/// <summary>
/// 事件外掛資訊表
/// </summary>
DataTable PluginInfoTable { get; set; }

/// <summary>
/// 事件列表
/// </summary>
string EventList { get; set; }

/// <summary>
/// 提示資訊
/// </summary>
string ToolTipText { get; set; }

/// <summary>
/// 提示多語言標識
/// </summary>
string ToolTipMessageCode { get; set; }

/// <summary>
/// 繫結事件
/// </summary>
/// <param name="valueControl">控制元件</param>
/// <param name="eventInfoTable">事件資訊表</param>
void BindingEvent(Control valueControl, DataTable eventInfoTable);

/// <summary>
/// 設定佈局
/// </summary>
void SetLayout();

/// <summary>
/// 控制元件被載入後呼叫的方法
/// 此方法在控制元件還原後被視窗呼叫
/// </summary>
void KzxControlLoaded();

/// <summary>
/// 控制元件事件
/// </summary>
event KzxControlOperateEventHandler KzxControlOperate;
/// <summary>
/// 獲取多語言文字事件
/// </summary>
event KzxGetLanguageEventHandler KzxGetLanguage;

  然後在剛剛新建的使用者控制元件實現這個介面,部分程式碼如下:

#region 佈局屬性
  private int _LayoutRow = 0;
  /// <summary>
  /// 佈局行號
  /// </summary>
  [Category("佈局"), Description("LayoutRow,佈局行號"), Browsable(false)]
  [McDisplayName("LayoutRow")]
  public int LayoutRow
  {
      get
      {
          if (this.DesignMode == true)
          {
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  this._LayoutRow = panel.GetRow(this);
              }
          }
          return this._LayoutRow;
      }
      set
      {
          this._LayoutRow = value;
          if (this.DesignMode == true)
          {
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  panel.SetRow(this, value);
              }
          }
      }
  }

  private int _LayoutRowSpan = 1;
  /// <summary>
  /// 佈局跨的行數
  /// </summary>
  [Category("佈局"), Description("LayoutRowSpan,佈局跨的行數"), Browsable(false)]
  [McDisplayName("LayoutRowSpan")]
  public int LayoutRowSpan
  {
      get
      {
          TableLayoutPanel panel = this.Parent as TableLayoutPanel;
          if (panel != null)
          {
              panel.SetRowSpan(this, this._LayoutRowSpan);
          }
          return this._LayoutRowSpan;
      }
      set
      {
          this._LayoutRowSpan = value;
          TableLayoutPanel panel = this.Parent as TableLayoutPanel;
          if (panel != null)
          {
              panel.SetRowSpan(this, value);
          }
      }
  }

  private int _LayoutColumn = 0;
  /// <summary>
  /// 佈局列號
  /// </summary>
  [Category("佈局"), Description("LayoutColumn,佈局列號"), Browsable(false)]
  [McDisplayName("LayoutColumn")]
  public int LayoutColumn
  {
      get
      {
          if (this.DesignMode == true)
          {
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  this._LayoutColumn = panel.GetColumn(this);
              }
          }
          return this._LayoutColumn;
      }
      set
      {
          this._LayoutColumn = value;
          if (this.DesignMode == true)
          {
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  panel.SetColumn(this, value);
              }
          }
      }
  }

  private int _LayoutColumnSpan = 1;
  /// <summary>
  /// 佈局跨的列數
  /// </summary>
  [Category("佈局"), Description("LayoutColumnSpan,佈局跨的列數"), Browsable(false)]
  [McDisplayName("LayoutColumnSpan")]
  public int LayoutColumnSpan
  {
      get
      {
          TableLayoutPanel panel = this.Parent as TableLayoutPanel;
          if (panel != null)
          {
              panel.SetColumnSpan(this, this._LayoutColumnSpan);
          }
          return this._LayoutColumnSpan;
      }
      set
      {
          this._LayoutColumnSpan = value;
          TableLayoutPanel panel = this.Parent as TableLayoutPanel;
          if (panel != null)
          {
              panel.SetColumnSpan(this, value);
          }
      }
  }

  #endregion

  為了效果明顯點,博主就拿ToolTip來舉例,以及部分事件程式碼如下:

private string _MessageCode = "0";
  /// <summary>
  /// 多語言環境下顯示文字的對應標識
  /// </summary>
  [Category("多語言"), Description("MessageCode,多語言環境下顯示文字的對應標識"), Browsable(true)]
  [McDisplayName("MessageCode")]
  public virtual string MessageCode
  {
      get
      {
          return this._MessageCode;
      }
      set
      {
          this._MessageCode = value;
      }
  }

  private string _DesigeCaption = string.Empty;
  /// <summary>
  /// 沒有多語言的情況下的預設顯示標題
  /// </summary>
  [Category("多語言"), Description("DesigeCaption,沒有多語言的情況下的預設顯示標題"), Browsable(true)]
  [McDisplayName("DesigeCaption")]
  public virtual string DesigeCaption
  {
      get
      {
          return this.Text.Trim();
      }
      set
      {
          this.Text = value;
      }
  }

  拿ToolTip舉個例子

#region 方法
  private DataTable _PluginInfoTable = KzxBaseControl.CreatePluginDataTable();
  [Category("自定義"), Description("PluginInfoTable,事件外掛資訊表"), Browsable(false)]
  [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  [McDisplayName("PluginInfoTable")]
  public DataTable PluginInfoTable
  {
      get
      {
          return this._PluginInfoTable;
      }
      set
      {
          this._PluginInfoTable = value;
          BindingEvent(this, this._PluginInfoTable);
      }
  }

  private string _ToolTipText = string.Empty;
  /// <summary>
  /// 提示資訊
  /// </summary>
  [Category("汽泡提示"), Description("ToolTipText,提示資訊"), Browsable(true)]
  [McDisplayName("ToolTipText")]
  public virtual string ToolTipText
  {
      get
      {
          return this._ToolTipText;
      }
      set
      {
          this._ToolTipText = value;
      }
  }

  private string _ToolTipMessageCode = string.Empty;
  /// <summary>
  /// 提示多語言標識
  /// </summary>
  [Category("汽泡提示"), Description("ToolTipMessageCode,提示資訊多語言標識"), Browsable(true)]
  [McDisplayName("ToolTipMessageCode")]
  public virtual string ToolTipMessageCode
  {
      get
      {
          return this._ToolTipMessageCode;
      }
      set
      {
          this._ToolTipMessageCode = value;
      }
  }

  private Color _LabelForeColor = Color.Black;
  /// <summary>
  /// 標籤字型顏色
  /// </summary>
  [Category("外觀"), Description("LabelForeColor,標籤字型顏色"), Browsable(true)]
  [McDisplayName("LabelForeColor")]
  public Color LabelForeColor
  {
      get
      {
          return this.ForeColor;
      }
      set
      {
          this._LabelForeColor = value;
          this.ForeColor = value;
      }
  }

  /// <summary>
  /// 控鈕型別
  /// </summary>
  [Category("外觀"), Description("YZButtonStyle,控鈕型別"), Browsable(true)]
  [McDisplayName("YZButtonStyle")] 
  public DevExpress.XtraEditors.Controls.BorderStyles YZButtonStyle
  {
      get
      {
          return this.ButtonStyle;
      }
      set
      {
          this.ButtonStyle = value;
      }
  }

  #endregion

  程式碼比較簡單,關鍵屬性和事件也已經添加了詳細備註,就不一一解釋了。使用者控制元件建立好後,我們就可以直接實用拖控制元件大法了。

  效果如下:

  實現控制元件按鈕,滑鼠懸浮提示框(ToolTip)外掛程式碼也比較簡單,具體如下:

     其中ssLoadMsgOrDefault方法,就是博文開頭提到的,資料庫儲存-鍵值對取值的方法,具體如下:

/// <summary>
  /// 根據Msg_ID取相應語言描述,獲取為空時顯示 emptyDisplayMsg
  /// </summary>
  /// <param name="msgID"></param>
  /// <param name="emptyDisplayMsg"></param>
  /// <returns></returns>
  public static string ssLoadMsgOrDefault(string msgID, string emptyDisplayMsg)
  {
      if (string.IsNullOrWhiteSpace(msgID))
          return emptyDisplayMsg;

      var msgText = string.Empty;
      if (SysVar.LanguageList.ContainsKey(msgID))
          msgText = SysVar.LanguageList[msgID];

      if (string.IsNullOrWhiteSpace(msgText))
          msgText = emptyDisplayMsg;

      return msgText;
  }

  為了方便處理多語言,博主還寫了個小軟體,用來儲存或生成多語言對應關係,這個後續會給大家介紹,好了,讓我們F5來看看具體效果:

  最後,由於後續所有重寫/重繪控制元件都在同一個專案使用,而且Dev系統引用檔案較多,壓縮後原始碼檔案仍然很大,如果有需要原始碼的朋友,可以微信公眾號聯絡博主,原始碼可以免費贈予~!有疑問的也可以CALL我一起探討,最最後,如果覺得本篇博文對您或者身邊朋友有幫助的,麻煩點個關注!贈人玫瑰,手留餘香,您的支援就是我寫作最大的動力,感謝您的關注,期待和您一起探討!再會!

&n