玩轉控件:擴展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我一起探討,最最后,如果覺得本篇博文對您或者身邊朋友有幫助的,麻煩點個關注!贈人玫瑰,手留余香,您的支持就是我寫作最大的動力,感謝您的關注,期待和您一起探討!再會!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM