玩轉控制項:封裝Dev的LabelControl和TextEdit

  • 2020 年 3 月 26 日
  • 筆記

  俗話說的好:”工欲善其事必先利其器”,作為軟體攻城獅也是同樣道理,攻城獅開發的軟體目的是簡化客戶的操作,讓客戶動動手指就可以完成很多事情,減少人力成本。這也是系統/軟體存在的目的。那對於攻城獅來說怎麼簡化自己的操作?讓自己也動動手指就可以減少很多重複的工作呢?如果你對此也有同樣的疑問或興趣,那就跟作者一起看下去吧!

  說到利器,自然而然的會想到宇宙第一IDE——Visual Studio 隨著版本的迭代,大大的加快了攻城獅的編碼效率。那對於我們自己開發的軟體,如何減少重複操作,加快軟體進度呢?這就是作者今日的主題——封裝控制項。

        作者幾年前有幸作為公司代表,到金蝶總部參觀,並學習當年金蝶最新科技——K3 Cloud,說實話,作者當年年輕氣盛,和普遍技術開發一樣,心高氣傲,對除自己研發以外的軟體不屑一顧,覺得自己才是最流P的!現在好了,善惡終有報,輪到自己爬著學習K3 Cloud的控制項封裝來造輪子了…

   想當年,金戈鐵馬,氣吞萬里如虎!….現如今,想起來都是淚…

        扯遠了,還是回到本篇的主題造輪子…哦,不!玩轉控制項!封裝自己的插件吧!

        今天作者主要介紹的是,封裝Dev的LabelControl和TextEdit。原因很簡單,說的好聽就是簡化自己重複操作,封裝前,拖控制項大法,先拖一個LabelControl ,完善它的屬性。在拖一個TextEdit,完善它的屬性,必要時還要完善它的控制項。你以為現在就完了嗎?不對,還要拖動一下,看看上下左右的對齊效果….emmmmm~

   Talk is Cheap,Show me the Code!

   首先我們先新建一個用戶控制項,繼承UserControl,為了減少冗餘程式碼,作者把命名為BaseControl,後續所有用戶控制項全部繼承此類。

public partial class KzxBaseControl : System.Windows.Forms.UserControl,IControl

   其中IControl介面主要用來聲明,控制項的一些屬性和事件,部分程式碼如下(程式碼篇幅較長,有需要公眾號call我,源碼免費贈送):

 /// <summary>      /// 控制項事件委託      /// </summary>      /// <param name="sender">事件發起者</param>      /// <param name="e">事件參數</param>      public delegate void KzxControlOperateEventHandler(object sender, ControlEventArgs e);        /// <summary>      /// 獲取多語言文本事件委託      /// </summary>      /// <param name="sender">事件發起者</param>      /// <param name="messageCode">語言標識</param>      /// <param name="text">多語言的文本</param>      public delegate void KzxGetLanguageEventHandler(object sender, string messageCode, ref string text);      public interface IControl      {          /// <summary>          /// 有Load方法          /// </summary>          bool HasLoad { get; }            /// <summary>          /// 被引用後允許修改          /// true允許,false不允許          /// </summary>          bool AllowEdit { get; set; }            /// <summary>          /// 多語言環境下顯示文本的對應標識          /// </summary>          string MessageCode { get; set; }            /// <summary>          /// 設計時的顯示,方便設計員工識別          /// </summary>          string DesigeCaption { get; set; }            /// <summary>          /// 控制項的唯一標識          /// </summary>          string Key { get; set; }            /// <summary>          /// True控制項可用,False控制項不可用          /// </summary>          Boolean Enabled { get; set; }            /// <summary>          /// True控制項可見,False控制項不可見          /// </summary>          Boolean Visible { get; set; }            /// <summary>          /// Tag標誌,用於存儲任何數據          /// </summary>          object Tag { get; set; }            /// <summary>          /// 設計時的可用性          /// </summary>          Boolean DesigeEnabled { get; set; }          ...          ...

   用戶控制項父類,主要集中所有用戶控制項的通用屬性、方法和事件,部分程式碼如下:

private bool _AllowEdit = true;    /// <summary>    /// 被引用後允許修改    /// true允許,false不允許    /// </summary>    [Category("驗證"), Description("AllowEdit,被引用後允許修改,true允許,false不允許"), Browsable(true)]    [McDisplayName("AllowEdit")]    public virtual bool AllowEdit    {        get        {            return this._AllowEdit;        }        set        {            this._AllowEdit = value;        }    }      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 = "顯示標題";    /// <summary>    /// 沒有多語言的情況下的默認顯示標題    /// </summary>    [Category("多語言"), Description("DesigeCaption,沒有多語言的情況下的默認顯示標題"), Browsable(true)]    [McDisplayName("DesigeCaption")]    public virtual string DesigeCaption    {        get        {            return this._DesigeCaption;        }        set        {            this._DesigeCaption = value;        }    }      private string _Key = string.Empty;    /// <summary>    /// 控制項的唯一標識    /// </summary>    [Category("數據"), Description("Key,控制項的唯一標識"), Browsable(true)]    [McDisplayName("Key")]    public virtual string Key    {        get        {            if (string.IsNullOrWhiteSpace(this._Key) == true)            {                if (string.IsNullOrWhiteSpace(this.Table) == false && string.IsNullOrWhiteSpace(this.Field) == false)                {                    this._Key = this.Table + "." + this.Field;                }                else if (string.IsNullOrWhiteSpace(this.Table) == false)                {                    this._Key = this.Table;                }            }            if (string.IsNullOrEmpty(this._Key)) return this.Name;              return this._Key;        }        set        {            this._Key = value;        }    }      private bool _DesigeEnabled = true;    /// <summary>    /// 設計時的可用性    /// </summary>    [Category("特性"), Description("DesigeEnabled,設計時的可用性"), Browsable(true)]    [McDisplayName("DesigeEnabled")]    public virtual bool DesigeEnabled    {        get        {            return this._DesigeEnabled;        }        set        {            this._DesigeEnabled = value;            //this.Enabled = value;        }    }      private bool _DesigeVisible = true;    /// <summary>    /// 設計時可見性    /// </summary>    [Category("特性"), Description("DesigeVisible,設計時可見性"), Browsable(true)]    [McDisplayName("DesigeVisible")]    public virtual bool DesigeVisible    {        get        {            return this._DesigeVisible;        }        set        {            this._DesigeVisible = value;            //this.Visible = value;            if (this.DesignMode == true)            {                if (value == false)                {                    this.BorderStyle = BorderStyle.Fixed3D;                }                else                {                    this.BorderStyle = BorderStyle.None;                }            }            else            {                //this.Visible = value;            }        }    }

 /// <summary>  /// 觸發控制項事件  /// </summary>  /// <param name="sender">事件發起者</param>  /// <param name="eventName">事件名稱</param>  /// <param name="e">事件參數</param>  protected virtual void RaiseEvent(object sender, string eventName, object e)  {      ControlEventArgs args = new ControlEventArgs();      args.CurrentControl = sender;      args.EventId = eventName;      args.SystemEventArgs = e;      args.FieldName = this.Field;      args.TableName = this.Table;      args.Key = this.Key;      if (this.KzxControlOperate != null)      {          this.KzxControlOperate(this, args);          e = args.SystemEventArgs;      }  }      private static MethodInfo _methodInfo = null;    /// <summary>  /// 獲取多語言文本  /// </summary>  /// <param name="messageCode">語言文本標識</param>  /// <param name="defaultMessage">默認的文本</param>  /// <returns>取到的文本</returns>  protected virtual string GetLanguage(string messageCode, string defaultMessage)  {      string text = string.Empty;        try      {          text = defaultMessage;          string filepath = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "KzxCommon.dll");          Assembly assembly = null;          object obj = null;            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();          for (int i = 0; i < assemblies.Length; i++)          {              if (assemblies[i].GetName().Name.Equals("KzxCommon", StringComparison.OrdinalIgnoreCase) == true)              {                  assembly = assemblies[i];                  break;              }          }          if (assembly == null)          {              assembly = Assembly.LoadFrom(filepath);          }          obj = assembly.CreateInstance("KzxCommon.sysClass");          text = defaultMessage;          if (_methodInfo == null)          {              if (obj != null)              {                  _methodInfo = obj.GetType().GetMethod("ssLoadMsg", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);                  if (_methodInfo != null)                  {                      text = _methodInfo.Invoke(obj, new object[] { messageCode }).ToString();                  }              }          }          else          {              text = _methodInfo.Invoke(obj, new object[] { messageCode }).ToString();          }      }      catch (Exception ex)      {        }      return string.IsNullOrWhiteSpace(text) == true ? defaultMessage : text;  }    protected virtual void OnKzxBaseControlLoad()  {      object obj = null;      PropertyInfo pi = null;      for (int i = 0; i < this.Controls.Count; i++)      {          if (this.Controls[i].Name.Equals("ValueControl", StringComparison.OrdinalIgnoreCase) == true)          {              pi = this.Controls[i].GetType().GetProperty("ErrorIconAlignment");              if (pi != null)              {                  pi.SetValue(this.Controls[i], ErrorIconAlignment.TopRight, null);              }          }      }  }    protected override void OnControlAdded(System.Windows.Forms.ControlEventArgs e)  {      base.OnControlAdded(e);      OnKzxBaseControlLoad();      SetAppearance();  }

  介紹完基類,我們新建在新建要給用戶控制項來繼承它,並實現業務需求:

    /// <summary>      /// 文本框驗證      /// </summary>      [ToolboxBitmapAttribute(typeof(Bitmap), "文本框")]      public partial class KzxTextBox : KzxBaseControl

   布局方面,應自己要求,氣運丹田,使出拖控制項大法!

   此處無需做任何屬性、事件設置。只需把我們日常常用到的屬性、事件,用特性標記起來即可。部分程式碼如下:

 private DevExpress.XtraEditors.Controls.BorderStyles _BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Default;  /// <summary>  /// 邊框顯示格式  /// </summary>  [Category("數據格式"), Description("KzxBorderStyle,邊框顯示格式"), Browsable(true)]  [McDisplayName("KzxBorderStyle")]  public override DevExpress.XtraEditors.Controls.BorderStyles KzxBorderStyle  {      get      {          return this.ValueControl.Properties.BorderStyle;      }      set      {          this._BorderStyle = value;          this.ValueControl.Properties.BorderStyle = value;      }  }    /// <summary>  /// 沒有多語言的情況下的默認顯示標題  /// </summary>  [Category("多語言"), Description("DesigeCaption,沒有多語言的情況下的默認顯示標題"), Browsable(true)]  [McDisplayName("DesigeCaption")]  public override string DesigeCaption  {      get      {          return this.CaptionControl.Text.Trim();      }      set      {          this.CaptionControl.Text = value;      }  }    private bool _IsNull = true;  /// <summary>  /// 可空性  /// </summary>  [Category("驗證"), Description("IsNull,可空性"), Browsable(true)]  [McDisplayName("IsNull")]  public override bool IsNull  {      get      {          SetBackColor();          return this._IsNull;      }      set      {          this._IsNull = value;          SetBackColor();      }  }    /// <summary>  /// 只讀性  /// </summary>  [Category("驗證"), Description("ReadOnly,只讀性"), Browsable(true)]  [McDisplayName("ReadOnly")]  public override bool ReadOnly  {      get      {          SetBackColor();          return this.ValueControl.Properties.ReadOnly;      }      set      {          this.ValueControl.Properties.ReadOnly = value;          SetBackColor();           if (value == false)          {              this.ValueControl.BackColor = Color.White;          }      }  }    private int maxLength = 0;  /// <summary>  /// 可錄入的最大長度  /// </summary>  [Category("驗證"), Description("MaxLength,可錄入的最大長度"), Browsable(true)]  [McDisplayName("MaxLength")]  public override int MaxLength  {      get      {          return maxLength;      }      set      {          maxLength = value;      }  }    private Int32 _CaptionLabelWidth = 75;  /// <summary>  /// 顯示標題寬度  /// </summary>  [Category("外觀"), Description("CaptionLabelWidth,顯示標題寬度"), Browsable(true)]  [McDisplayName("CaptionLabelWidth")]  public Int32 CaptionLabelWidth  {      get      {          return this.CaptionControl.Width;      }      set      {          this._CaptionLabelWidth = value;          this.CaptionControl.Width = value;      }  }    private string toolTipMaxLengthText = string.Empty;  /// <summary>  /// 數據長度不能超過資料庫長度提示文本  /// </summary>  public override string ToolTipMaxLengthText  {      get { return toolTipMaxLengthText; }      set { toolTipMaxLengthText = value; }  }    /// <summary>  /// 提示資訊  /// </summary>  [Category("汽泡提示"), Description("ToolTipText,提示資訊"), Browsable(true)]  [McDisplayName("ToolTipText")]  public override string ToolTipText  {      get      {          return (ValueControl == null) == true ? string.Empty : ValueControl.ToolTip;      }      set      {          if (ValueControl != null)          {              ValueControl.ToolTip = value;          }          if (CaptionControl != null)          {              CaptionControl.ToolTip = value;          }      }  }        private string _ToolTipMessageCode = string.Empty;  /// <summary>  /// 提示多語言標識  /// </summary>  [Category("汽泡提示"), Description("ToolTipMessageCode,提示資訊多語言標識"), Browsable(true)]  [McDisplayName("ToolTipMessageCode")]  public override string ToolTipMessageCode  {      get      {          return this._ToolTipMessageCode;      }      set      {          this._ToolTipMessageCode = value;      }  }

    一起看看用戶控制項效果以及封裝的屬性事件:

    F5看看運行效果:

    Done! 一個控制項,減少一半操作量! 在此,本控制項當作作者拋磚引玉,看官們可以根據自己實際情況進行數據封裝。有效的封裝,避免畫蛇添足哦~

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