俗话说的好:"工欲善其事必先利其器",作为软件攻城狮也是同样道理,攻城狮开发的软件目的是简化客户的操作,让客户动动手指就可以完成很多事情,减少人力成本。这也是系统/软件存在的目的。那对于攻城狮来说怎么简化自己的操作?让自己也动动手指就可以减少很多重复的工作呢?如果你对此也有同样的疑问或兴趣,那就跟作者一起看下去吧!

  说到利器,自然而然的会想到宇宙第一IDE——Visual Studio 随着版本的迭代,大大的加快了攻城狮的编码效率。那对于我们自己开发的软件,如何减少重复操作,加快软件进度呢?这就是作者今日的主题——封装控件。

作者几年前有幸作为公司代表,到金蝶总部参观,并学习当年金蝶最新科技——K3 Cloud,说实话,作者当年年轻气盛,和普遍技术开发一样,心高气傲,对除自己研发以外的软件不屑一顾,觉得自己才是最流P的!现在好了,善恶终有报,轮到自己爬着学习K3 Cloud的控件封装来造轮子了...

  想当年,金戈铁马,气吞万里如虎!....现如今,想起来都是泪...

扯远了,还是回到本篇的主题造轮子...哦,不!玩转控件!封装自己的插件吧!

今天作者主要介绍的是,封装Dev的LabelControl和TextEdit。原因很简单,说的好听就是简化自己重复操作,封装前,拖控件大法,先拖一个LabelControl ,完善它的属性。在拖一个TextEdit,完善它的属性,必要时还要完善它的控件。你以为现在就完了吗?不对,还要拖动一下,看看上下左右的对齐效果....emmmmm~

   Talk is Cheap,Show me the Code!

   首先我们先新建一个用户控件,继承UserControl,为了减少冗余代码,作者把命名为BaseControl,后续所有用户控件全部继承此类。

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

  其中IControl接口主要用来声明,控件的一些属性和事件,部分代码如下(代码篇幅较长,有需要公众号call我,源码免费赠送):

  1. /// <summary>
  2. /// 控件事件委托
  3. /// </summary>
  4. /// <param name="sender">事件发起者</param>
  5. /// <param name="e">事件参数</param>
  6. public delegate void KzxControlOperateEventHandler(object sender, ControlEventArgs e);
  7.  
  8. /// <summary>
  9. /// 获取多语言文本事件委托
  10. /// </summary>
  11. /// <param name="sender">事件发起者</param>
  12. /// <param name="messageCode">语言标识</param>
  13. /// <param name="text">多语言的文本</param>
  14. public delegate void KzxGetLanguageEventHandler(object sender, string messageCode, ref string text);
  15. public interface IControl
  16. {
  17. /// <summary>
  18. /// 有Load方法
  19. /// </summary>
  20. bool HasLoad { get; }
  21.  
  22. /// <summary>
  23. /// 被引用后允许修改
  24. /// true允许,false不允许
  25. /// </summary>
  26. bool AllowEdit { get; set; }
  27.  
  28. /// <summary>
  29. /// 多语言环境下显示文本的对应标识
  30. /// </summary>
  31. string MessageCode { get; set; }
  32.  
  33. /// <summary>
  34. /// 设计时的显示,方便设计员工识别
  35. /// </summary>
  36. string DesigeCaption { get; set; }
  37.  
  38. /// <summary>
  39. /// 控件的唯一标识
  40. /// </summary>
  41. string Key { get; set; }
  42.  
  43. /// <summary>
  44. /// True控件可用,False控件不可用
  45. /// </summary>
  46. Boolean Enabled { get; set; }
  47.  
  48. /// <summary>
  49. /// True控件可见,False控件不可见
  50. /// </summary>
  51. Boolean Visible { get; set; }
  52.  
  53. /// <summary>
  54. /// Tag标志,用于存储任何数据
  55. /// </summary>
  56. object Tag { get; set; }
  57.  
  58. /// <summary>
  59. /// 设计时的可用性
  60. /// </summary>
  61. Boolean DesigeEnabled { get; set; }
  62. ...
  63. ...

  用户控件父类,主要集中所有用户控件的通用属性、方法和事件,部分代码如下:

  1. private bool _AllowEdit = true;
  2. /// <summary>
  3. /// 被引用后允许修改
  4. /// true允许,false不允许
  5. /// </summary>
  6. [Category("验证"), Description("AllowEdit,被引用后允许修改,true允许,false不允许"), Browsable(true)]
  7. [McDisplayName("AllowEdit")]
  8. public virtual bool AllowEdit
  9. {
  10. get
  11. {
  12. return this._AllowEdit;
  13. }
  14. set
  15. {
  16. this._AllowEdit = value;
  17. }
  18. }
  19.  
  20. private string _MessageCode = "";
  21. /// <summary>
  22. /// 多语言环境下显示文本的对应标识
  23. /// </summary>
  24. [Category("多语言"), Description("MessageCode,多语言环境下显示文本的对应标识"), Browsable(true)]
  25. [McDisplayName("MessageCode")]
  26. public virtual string MessageCode
  27. {
  28. get
  29. {
  30. return this._MessageCode;
  31. }
  32. set
  33. {
  34. this._MessageCode = value;
  35. }
  36. }
  37.  
  38. private string _DesigeCaption = "显示标题";
  39. /// <summary>
  40. /// 没有多语言的情况下的默认显示标题
  41. /// </summary>
  42. [Category("多语言"), Description("DesigeCaption,没有多语言的情况下的默认显示标题"), Browsable(true)]
  43. [McDisplayName("DesigeCaption")]
  44. public virtual string DesigeCaption
  45. {
  46. get
  47. {
  48. return this._DesigeCaption;
  49. }
  50. set
  51. {
  52. this._DesigeCaption = value;
  53. }
  54. }
  55.  
  56. private string _Key = string.Empty;
  57. /// <summary>
  58. /// 控件的唯一标识
  59. /// </summary>
  60. [Category("数据"), Description("Key,控件的唯一标识"), Browsable(true)]
  61. [McDisplayName("Key")]
  62. public virtual string Key
  63. {
  64. get
  65. {
  66. if (string.IsNullOrWhiteSpace(this._Key) == true)
  67. {
  68. if (string.IsNullOrWhiteSpace(this.Table) == false && string.IsNullOrWhiteSpace(this.Field) == false)
  69. {
  70. this._Key = this.Table + "." + this.Field;
  71. }
  72. else if (string.IsNullOrWhiteSpace(this.Table) == false)
  73. {
  74. this._Key = this.Table;
  75. }
  76. }
  77. if (string.IsNullOrEmpty(this._Key)) return this.Name;
  78.  
  79. return this._Key;
  80. }
  81. set
  82. {
  83. this._Key = value;
  84. }
  85. }
  86.  
  87. private bool _DesigeEnabled = true;
  88. /// <summary>
  89. /// 设计时的可用性
  90. /// </summary>
  91. [Category("特性"), Description("DesigeEnabled,设计时的可用性"), Browsable(true)]
  92. [McDisplayName("DesigeEnabled")]
  93. public virtual bool DesigeEnabled
  94. {
  95. get
  96. {
  97. return this._DesigeEnabled;
  98. }
  99. set
  100. {
  101. this._DesigeEnabled = value;
  102. //this.Enabled = value;
  103. }
  104. }
  105.  
  106. private bool _DesigeVisible = true;
  107. /// <summary>
  108. /// 设计时可见性
  109. /// </summary>
  110. [Category("特性"), Description("DesigeVisible,设计时可见性"), Browsable(true)]
  111. [McDisplayName("DesigeVisible")]
  112. public virtual bool DesigeVisible
  113. {
  114. get
  115. {
  116. return this._DesigeVisible;
  117. }
  118. set
  119. {
  120. this._DesigeVisible = value;
  121. //this.Visible = value;
  122. if (this.DesignMode == true)
  123. {
  124. if (value == false)
  125. {
  126. this.BorderStyle = BorderStyle.Fixed3D;
  127. }
  128. else
  129. {
  130. this.BorderStyle = BorderStyle.None;
  131. }
  132. }
  133. else
  134. {
  135. //this.Visible = value;
  136. }
  137. }
  138. }
  1. /// <summary>
  2. /// 触发控件事件
  3. /// </summary>
  4. /// <param name="sender">事件发起者</param>
  5. /// <param name="eventName">事件名称</param>
  6. /// <param name="e">事件参数</param>
  7. protected virtual void RaiseEvent(object sender, string eventName, object e)
  8. {
  9. ControlEventArgs args = new ControlEventArgs();
  10. args.CurrentControl = sender;
  11. args.EventId = eventName;
  12. args.SystemEventArgs = e;
  13. args.FieldName = this.Field;
  14. args.TableName = this.Table;
  15. args.Key = this.Key;
  16. if (this.KzxControlOperate != null)
  17. {
  18. this.KzxControlOperate(this, args);
  19. e = args.SystemEventArgs;
  20. }
  21. }
  22.  
  23. private static MethodInfo _methodInfo = null;
  24.  
  25. /// <summary>
  26. /// 获取多语言文本
  27. /// </summary>
  28. /// <param name="messageCode">语言文本标识</param>
  29. /// <param name="defaultMessage">默认的文本</param>
  30. /// <returns>取到的文本</returns>
  31. protected virtual string GetLanguage(string messageCode, string defaultMessage)
  32. {
  33. string text = string.Empty;
  34.  
  35. try
  36. {
  37. text = defaultMessage;
  38. string filepath = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "KzxCommon.dll");
  39. Assembly assembly = null;
  40. object obj = null;
  41.  
  42. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  43. for (int i = ; i < assemblies.Length; i++)
  44. {
  45. if (assemblies[i].GetName().Name.Equals("KzxCommon", StringComparison.OrdinalIgnoreCase) == true)
  46. {
  47. assembly = assemblies[i];
  48. break;
  49. }
  50. }
  51. if (assembly == null)
  52. {
  53. assembly = Assembly.LoadFrom(filepath);
  54. }
  55. obj = assembly.CreateInstance("KzxCommon.sysClass");
  56. text = defaultMessage;
  57. if (_methodInfo == null)
  58. {
  59. if (obj != null)
  60. {
  61. _methodInfo = obj.GetType().GetMethod("ssLoadMsg", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
  62. if (_methodInfo != null)
  63. {
  64. text = _methodInfo.Invoke(obj, new object[] { messageCode }).ToString();
  65. }
  66. }
  67. }
  68. else
  69. {
  70. text = _methodInfo.Invoke(obj, new object[] { messageCode }).ToString();
  71. }
  72. }
  73. catch (Exception ex)
  74. {
  75.  
  76. }
  77. return string.IsNullOrWhiteSpace(text) == true ? defaultMessage : text;
  78. }
  79.  
  80. protected virtual void OnKzxBaseControlLoad()
  81. {
  82. object obj = null;
  83. PropertyInfo pi = null;
  84. for (int i = ; i < this.Controls.Count; i++)
  85. {
  86. if (this.Controls[i].Name.Equals("ValueControl", StringComparison.OrdinalIgnoreCase) == true)
  87. {
  88. pi = this.Controls[i].GetType().GetProperty("ErrorIconAlignment");
  89. if (pi != null)
  90. {
  91. pi.SetValue(this.Controls[i], ErrorIconAlignment.TopRight, null);
  92. }
  93. }
  94. }
  95. }
  96.  
  97. protected override void OnControlAdded(System.Windows.Forms.ControlEventArgs e)
  98. {
  99. base.OnControlAdded(e);
  100. OnKzxBaseControlLoad();
  101. SetAppearance();
  102. }

  介绍完基类,我们新建在新建要给用户控件来继承它,并实现业务需求:

  1. /// <summary>
  2. /// 文本框验证
  3. /// </summary>
  4. [ToolboxBitmapAttribute(typeof(Bitmap), "文本框")]
  5. public partial class KzxTextBox : KzxBaseControl

  布局方面,应自己要求,气运丹田,使出拖控件大法!

  此处无需做任何属性、事件设置。只需把我们日常常用到的属性、事件,用特性标记起来即可。部分代码如下:

  1. private DevExpress.XtraEditors.Controls.BorderStyles _BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Default;
  2. /// <summary>
  3. /// 边框显示格式
  4. /// </summary>
  5. [Category("数据格式"), Description("KzxBorderStyle,边框显示格式"), Browsable(true)]
  6. [McDisplayName("KzxBorderStyle")]
  7. public override DevExpress.XtraEditors.Controls.BorderStyles KzxBorderStyle
  8. {
  9. get
  10. {
  11. return this.ValueControl.Properties.BorderStyle;
  12. }
  13. set
  14. {
  15. this._BorderStyle = value;
  16. this.ValueControl.Properties.BorderStyle = value;
  17. }
  18. }
  19.  
  20. /// <summary>
  21. /// 没有多语言的情况下的默认显示标题
  22. /// </summary>
  23. [Category("多语言"), Description("DesigeCaption,没有多语言的情况下的默认显示标题"), Browsable(true)]
  24. [McDisplayName("DesigeCaption")]
  25. public override string DesigeCaption
  26. {
  27. get
  28. {
  29. return this.CaptionControl.Text.Trim();
  30. }
  31. set
  32. {
  33. this.CaptionControl.Text = value;
  34. }
  35. }
  36.  
  37. private bool _IsNull = true;
  38. /// <summary>
  39. /// 可空性
  40. /// </summary>
  41. [Category("验证"), Description("IsNull,可空性"), Browsable(true)]
  42. [McDisplayName("IsNull")]
  43. public override bool IsNull
  44. {
  45. get
  46. {
  47. SetBackColor();
  48. return this._IsNull;
  49. }
  50. set
  51. {
  52. this._IsNull = value;
  53. SetBackColor();
  54. }
  55. }
  56.  
  57. /// <summary>
  58. /// 只读性
  59. /// </summary>
  60. [Category("验证"), Description("ReadOnly,只读性"), Browsable(true)]
  61. [McDisplayName("ReadOnly")]
  62. public override bool ReadOnly
  63. {
  64. get
  65. {
  66. SetBackColor();
  67. return this.ValueControl.Properties.ReadOnly;
  68. }
  69. set
  70. {
  71. this.ValueControl.Properties.ReadOnly = value;
  72. SetBackColor();
  73. if (value == false)
  74. {
  75. this.ValueControl.BackColor = Color.White;
  76. }
  77. }
  78. }
  79.  
  80. private int maxLength = ;
  81. /// <summary>
  82. /// 可录入的最大长度
  83. /// </summary>
  84. [Category("验证"), Description("MaxLength,可录入的最大长度"), Browsable(true)]
  85. [McDisplayName("MaxLength")]
  86. public override int MaxLength
  87. {
  88. get
  89. {
  90. return maxLength;
  91. }
  92. set
  93. {
  94. maxLength = value;
  95. }
  96. }
  97.  
  98. private Int32 _CaptionLabelWidth = ;
  99. /// <summary>
  100. /// 显示标题宽度
  101. /// </summary>
  102. [Category("外观"), Description("CaptionLabelWidth,显示标题宽度"), Browsable(true)]
  103. [McDisplayName("CaptionLabelWidth")]
  104. public Int32 CaptionLabelWidth
  105. {
  106. get
  107. {
  108. return this.CaptionControl.Width;
  109. }
  110. set
  111. {
  112. this._CaptionLabelWidth = value;
  113. this.CaptionControl.Width = value;
  114. }
  115. }
  116.  
  117. private string toolTipMaxLengthText = string.Empty;
  118. /// <summary>
  119. /// 数据长度不能超过数据库长度提示文本
  120. /// </summary>
  121. public override string ToolTipMaxLengthText
  122. {
  123. get { return toolTipMaxLengthText; }
  124. set { toolTipMaxLengthText = value; }
  125. }
  126.  
  127. /// <summary>
  128. /// 提示信息
  129. /// </summary>
  130. [Category("汽泡提示"), Description("ToolTipText,提示信息"), Browsable(true)]
  131. [McDisplayName("ToolTipText")]
  132. public override string ToolTipText
  133. {
  134. get
  135. {
  136. return (ValueControl == null) == true ? string.Empty : ValueControl.ToolTip;
  137. }
  138. set
  139. {
  140. if (ValueControl != null)
  141. {
  142. ValueControl.ToolTip = value;
  143. }
  144. if (CaptionControl != null)
  145. {
  146. CaptionControl.ToolTip = value;
  147. }
  148. }
  149. }
  150.  
  151. private string _ToolTipMessageCode = string.Empty;
  152. /// <summary>
  153. /// 提示多语言标识
  154. /// </summary>
  155. [Category("汽泡提示"), Description("ToolTipMessageCode,提示信息多语言标识"), Browsable(true)]
  156. [McDisplayName("ToolTipMessageCode")]
  157. public override string ToolTipMessageCode
  158. {
  159. get
  160. {
  161. return this._ToolTipMessageCode;
  162. }
  163. set
  164. {
  165. this._ToolTipMessageCode = value;
  166. }
  167. }

    一起看看用户控件效果以及封装的属性事件:

    F5看看运行效果:

  Done! 一个控件,减少一半操作量! 在此,本控件当作作者抛砖引玉,看官们可以根据自己实际情况进行数据封装。有效的封装,避免画蛇添足哦~

最后,由于后续所有重写/重绘控件都在同一个项目使用,而且Dev系统引用文件较多,压缩后源码文件仍然很大,如果有需要源码的朋友,可以微信公众号联系博主,源码可以免费赠予~!有疑问的也可以CALL我一起探讨,最最后,如果觉得本篇博文对您或者身边朋友有帮助的,麻烦点个关注!赠人玫瑰,手留余香,您的支持就是我写作最大的动力,感谢您的关注,期待和您一起探讨!再会!

玩转控件:封装Dev的LabelControl和TextEdit的更多相关文章

  1. 玩转控件:封装Dev的SearchLookupEdit

    鸣谢 随着前面几个章节对控件封装与扩展的分享,不少小伙伴儿们在作者公众号上反馈,并联系作者,表示通过这些系列和源码能学到不少细节上的东西,并运用到了自己的实际项目当中,也有不少伙伴儿反馈更好更优的处理 ...

  2. 玩转控件:对Dev的GridControl控件扩展

    缘由 一切实现来源于需求,目的在于不盲目造轮子,有小伙伴儿在看了<玩转控件:对Dev中GridControl控件的封装和扩展>文章后,私信作者说,因公司业务逻辑比较复杂,展示字段比较多,尤 ...

  3. 玩转控件:扩展Dev中SimpleButton

    何为扩展,顾名思义,就是在原有控件属性.事件的基础上拓展自己需要或实用的属性.事件等等.或者可以理解为,现有的控件已经不能完全满足我(的需求)了.好的扩展会使控件更加完善,实用,好用.不好的扩展,说白 ...

  4. 玩转控件:对Dev中GridControl控件的封装和扩展

    又是一年清明节至,细雨绵绵犹如泪光,树叶随风摆动.... 转眼间,一年又过去了三分之一,疫情的严峻让不少企业就跟清明时节的树叶一样,摇摇欲坠.裁员的裁员,降薪的降薪,996的996~~说起来都是泪,以 ...

  5. 玩转控件:Fucking ERP之流程图

    前言 首先,跟守护在作者公众号和私信作者催更的朋友们道个歉.疫情的原因,公司从年初到现在一直处于996+的高压模式,导致公众号更新频率较低.而且作者每更新一篇原创公众号,既要对自己沉淀知识负责,也要对 ...

  6. 玩转控件:重写/重绘Dev中MessageBox弹窗控件

    很久没有更新博客了,本想着直接发一篇<手撕ERP>系列,从控件重写.重绘,到框架搭建,再到部分模块实现+业务的.但是每次动手的时候,都觉得难以下手.直接从数据库设计开始吧,模块设计还没定下 ...

  7. 玩转控件:重绘DEVEXPRESS中DateEdit控件 —— 让DateEdit支持只选择年月 (提供源码下载)

      前言 上一篇博文<玩转控件:重绘ComboBox —— 让ComboBox多列显示>中,根据大家的回馈,ComboBox已经支持筛选了,更新见博文最后最后最后面.   奇葩 这两天遇到 ...

  8. 控件使用经验-MVP模式+控件封装

    项目背景 几年前参与了一个面向学校的人事管理软件的开发,基于WinForm平台.今天主要想谈一谈其中关于控件的使用经验.这个项目我们大量使用了第三方控件.由于这个产品的生命周期很长,我们在设计时要考虑 ...

  9. 尝试使用UISearchDisplayController及对苹果对控件封装习惯的理解

    本文转载至 http://blog.sina.com.cn/s/blog_74e9d98d01019vji.html   在之前做过的应用中,很多都有“搜索”这个功能,大部分情况下我都是只采用UISe ...

随机推荐

  1. <USACO09DEC>过路费Cow Toll Pathsの思路

    啊好气 在洛谷上A了之后 隔壁jzoj总wa 迷茫了很久.发现那题要文件输入输出 生气 肥肠不爽 Description 跟所有人一样,农夫约翰以着宁教我负天下牛,休叫天下牛负我的伟大精神,日日夜夜苦 ...

  2. 对RLC重排序窗口大小的一点讨论

    在LTE协议栈的PDCP层和RLC层,都有一个重排序窗口(reordering window),主要用来保证数据的可靠传输,PDCP层的重排序窗口主要用于handover时保证数据的可靠传输,这里暂且 ...

  3. Python利用元类来控制实例创建

    问题: 改变实例创建方式,以此来实现单例模式,缓存或者其他类似的特性. 解决方法: 如果想定制化创建实例的过程,可以通过定制一个元类并以某种方式重新实现它的__call__()方法. 使用元类的单例模 ...

  4. Linux下多线程复制文件(C)

    Linux下实现多线程文件复制,使用<pthread.h>提供的函数: int pthread_create(pthread_t *thread,const pthread_attr_t ...

  5. leetcode_315_逆序对问题

    题目描述 本题来自于Leetcode的算法题库第315题,具体题目描述如下: 给定一个nums整数数组 ,按要求返回一个counts新数组 .数组 counts 有该性质: counts[i]的值是 ...

  6. hiho一下:Beautiful String

    hiho一下:Beautiful String 记不清这是 hiho一下第几周的题目了,题目不难,不过对于练习编程,训练思维很有帮助.况且当时笔者处于学习算法的早期, 所以也希望刚接触算法的同学能多去 ...

  7. vagrant 虚拟机配置最佳实践

    Mac VirtualBox Vagrant 管理虚拟机 这篇文章定位是在理解了 vagrant 相关概念之后,教你如何灵活玩转自己的虚拟机配置 本文为 @favoorr 常用的 Mac Virtua ...

  8. linux 的uuid码

    在提到这个之前,有个概念,就是什么是uuid呢? UUID码全称是通用唯一识别码 (Universally Unique Identifier, UUID),它 是一个软件建构的标准,亦为自由软件基金 ...

  9. VMWare vCenter 4.x 数据库由SQL Express 迁移至SQL Server 2008 R2

    默认安装下的 VMware vCenter 4.x 会在本地安装 SQL Express 2005 版本,如果你有需要迁移至 Full SQL Server版本比如 SQL Server 2008 R ...

  10. #2020.1.26笔记——springdatajpa

    2020.1.26笔记--springdatajpa 使用jpa的步骤: 1. 导入maven坐标 <?xml version="1.0" encoding="UT ...