玩轉控制元件:封裝Dev的LabelControl和TextEdit
俗話說的好:"工欲善其事必先利其器",作為軟體攻城獅也是同樣道理,攻城獅開發的軟體目的是簡化客戶的操作,讓客戶動動手指就可以完成很多事情,減少人力成本。這也是系統/軟體存在的目的。那對於攻城獅來說怎麼簡化自己的操作?讓自己也動動手指就可以減少很多重複的工作呢?如果你對此也有同樣的疑問或興趣,那就跟作者一起看下去吧!
說到利器,自然而然的會想到宇宙第一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我一起探討,最最後,如果覺得本篇博文對您或者身邊朋友有幫助的,麻煩點個關注!贈人玫瑰,手留餘香,您的支援就是我寫作最大的動力,感謝您的關注,期待和您一起探討!再會!