• 多年前写的文本框扩展控件(有ValueChanging事件等),已放github


    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。

    文章是哥(mephisto)写的,SourceLink

    阅读目录

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。

    文章是哥(mephisto)写的,SourceLink

    介绍

        这个TextBoxEx控件是cs下的,为了广大的框架都能用,就基于Framework2.0,主要有原来的textbox的功能,然后追加了EditValueChanging,数字类型输入,最大值,最小值。大家可以看完后追加下功能,比如正则输入。

    起因

     

          也是5年前的事情了,当时在做cs,一般cs都会用第三方控件,比如Dev等,dev中就有很多人性化的控件,比如我们用的比较多textbox,他就有EditValueChanging事件,当时我就想,不可能所以的小项目还要用到dev,那又想自己用到这么方便的控件怎么办,于是我就开始自己做了这个控件,抛砖引玉,只是丰富了一点,但确实对我那个年代的技术提高起了些许作用。

    代码

      我们先看下项目结构,因为就一个扩展控件,所以整体上看,组织结构很简单。如图:

    在ControlsEx这个工程中,主要一个自定义的事件所需参数ChangingEventArgs和一个扩展控件TextBoxEx

    一:ChangingEventArgs:

         主要定义EditValueChanging所需的数据结构。

     1     /// <summary>
     2     /// 正在改变EventArgs
     3     /// </summary>
     4     public class ChangingEventArgs : CancelEventArgs
     5     {
     6         private object newValue;
     7         private object oldValue;
     8 
     9         /// <summary>
    10         /// 正在改变EventArgs
    11         /// </summary>
    12         /// <param name="oldValue">原值</param>
    13         /// <param name="newValue">新值</param>
    14         public ChangingEventArgs(object oldValue, object newValue)
    15             : this(oldValue, newValue, false)
    16         {
    17         }
    18 
    19         /// <summary>
    20         /// 正在改变EventArgs
    21         /// </summary>
    22         /// <param name="oldValue">原值</param>
    23         /// <param name="newValue">新值</param>
    24         /// <param name="cancel">是否取消</param>
    25         public ChangingEventArgs(object oldValue, object newValue, bool cancel)
    26             : base(cancel)
    27         {
    28             this.oldValue = oldValue;
    29             this.newValue = newValue;
    30         }
    31 
    32         /// <summary>
    33         /// 新值
    34         /// </summary>
    35         public object NewValue
    36         {
    37             get
    38             {
    39                 return this.newValue;
    40             }
    41             set
    42             {
    43                 this.newValue = value;
    44             }
    45         }
    46 
    47         /// <summary>
    48         /// 原值
    49         /// </summary>
    50         public object OldValue
    51         {
    52             get
    53             {
    54                 return this.oldValue;
    55             }
    56         }
    57     }
    View Code

    二:TextBoxEx控件

         提供扩展的textbox功能。

    1.委托及事件定义

         这里没有简单的用事件参数,还是使用了事件属性,大家如果感兴趣,可以去看下msdn对这两块的解释,也没用简单的使用Action,因为你设计的时候写的简单了,方便了,易用了,但是别人调用的时候就不简单,方便了。

     1         /// <summary>
     2         /// 改变中事件句柄
     3         /// </summary>
     4         /// <param name="sender"></param>
     5         /// <param name="e"></param>
     6         public delegate void ChangingEventHandler(object sender, ChangingEventArgs e);
     7 
     8         /// <summary>
     9         /// <para>值改变中事件
    10         /// </para>
    11         /// </summary>
    12         [Description("值改变中事件"), Category("事件")]
    13         public event ChangingEventHandler EditValueChanging
    14         {
    15             add
    16             {
    17                 base.Events.AddHandler(editValueChanging, value);
    18             }
    19             remove
    20             {
    21                 base.Events.RemoveHandler(editValueChanging, value);
    22             }
    23         } 
    View Code

    2.设计器阶段的界面输入
         为了方便使用,就加入了设计器阶段属性,方便简单的输入。

     1         /// <summary>
     2         /// 输入的最大值
     3         /// </summary>
     4         [Description("输入的最大值")]
     5         public Int32 MaxNum
     6         {
     7             get { return _maxNum; }
     8             set { _maxNum = value; }
     9         }
    10         /// <summary>
    11         /// 输入的最小值
    12         /// </summary>
    13         [Description("输入的最小值")]
    14         public Int32 MinNum
    15         {
    16             get { return _minNum; }
    17             set
    18             {
    19                 if (value <= 0)
    20                     _minNum = value;
    21             }
    22         }
    23         /// <summary>
    24         /// 输入值类型
    25         /// </summary>
    26         [Description("输入值类型")]
    27         public ValueType EditValueType
    28         {
    29             get { return _editValueType; }
    30             set
    31             {
    32                 _editValueType = value;
    33                 //设置初始值
    34                 if (value == ValueType.Number)
    35                 {
    36                     EditValue = 0;
    37                 }
    38                 else
    39                     EditValue = null;
    40             }
    41         }
    View Code

    3.整体代码
       其实也没什么技术含量,只是提供个思路。

      1     public class TextBoxEx:TextBox
      2     {
      3         #region 委托
      4         /// <summary>
      5         /// 改变中事件句柄
      6         /// </summary>
      7         /// <param name="sender"></param>
      8         /// <param name="e"></param>
      9         public delegate void ChangingEventHandler(object sender, ChangingEventArgs e);
     10         #endregion
     11 
     12         #region 参数
     13         private Int32 _maxNum = Int32.MaxValue;//最大值
     14         private Int32 _minNum = Int32.MinValue;//最小值
     15         private ValueType _editValueType = ValueType.String;
     16         private static readonly object editValueChanging = new object();//EditValueChanging事件对应的Key
     17         #endregion
     18 
     19         #region Protected 参数
     20         /// <summary>
     21         /// 编制值
     22         /// </summary>
     23         protected object fEditValue = null;
     24         /// <summary>
     25         /// 编辑原始值
     26         /// </summary>
     27         protected object fOldEditValue = null; 
     28         #endregion
     29 
     30         #region 公有属性
     31         /// <summary>
     32         /// 输入的最大值
     33         /// </summary>
     34         [Description("输入的最大值")]
     35         public Int32 MaxNum
     36         {
     37             get { return _maxNum; }
     38             set { _maxNum = value; }
     39         }
     40         /// <summary>
     41         /// 输入的最小值
     42         /// </summary>
     43         [Description("输入的最小值")]
     44         public Int32 MinNum
     45         {
     46             get { return _minNum; }
     47             set
     48             {
     49                 if (value <= 0)
     50                     _minNum = value;
     51             }
     52         }
     53         /// <summary>
     54         /// 输入值类型
     55         /// </summary>
     56         [Description("输入值类型")]
     57         public ValueType EditValueType
     58         {
     59             get { return _editValueType; }
     60             set
     61             {
     62                 _editValueType = value;
     63                 //设置初始值
     64                 if (value == ValueType.Number)
     65                 {
     66                     EditValue = 0;
     67                 }
     68                 else
     69                     EditValue = null;
     70             }
     71         }
     72      
     73         #endregion
     74 
     75         #region 事件属性
     76         /// <summary>
     77         /// <para>值改变中事件
     78         /// </para>
     79         /// </summary>
     80         [Description("值改变中事件"), Category("事件")]
     81         public event ChangingEventHandler EditValueChanging
     82         {
     83             add
     84             {
     85                 base.Events.AddHandler(editValueChanging, value);
     86             }
     87             remove
     88             {
     89                 base.Events.RemoveHandler(editValueChanging, value);
     90             }
     91         }  
     92         #endregion
     93 
     94         #region 私有属性
     95         /// <summary>
     96         /// 编辑值
     97         /// </summary>
     98         private object EditValue
     99         {
    100             get { return fEditValue; }
    101             set
    102             {
    103                 if (EditValue == value) return;
    104                 OnEditValueChanging(new ChangingEventArgs(fEditValue, value));
    105                 this.Text = fEditValue == null ? null : fEditValue.ToString();
    106             }
    107         }
    108         #endregion
    109 
    110         #region 事件
    111         /// <summary>
    112         /// 编辑值正在改变事件
    113         /// </summary>
    114         /// <param name="e"></param>
    115         protected virtual void OnEditValueChanging(ChangingEventArgs e)
    116         {
    117             //调用注册的事件
    118             ReiseEditValueChanging(e);
    119 
    120             if (e.Cancel)//注册的事件取消 还原值
    121             {
    122                 fEditValue = e.OldValue;
    123                 return;
    124             }
    125 
    126             switch (_editValueType)
    127             {
    128                 case ValueType.Number://数值类型
    129                     {
    130                         if (e.NewValue != null && !string.IsNullOrEmpty(e.NewValue.ToString()))//非空值
    131                         {
    132                             int intNewNum = 0;
    133                             if (!Int32.TryParse(e.NewValue.ToString(), out intNewNum))//非数字
    134                             {
    135                                 string strOp = e.NewValue.ToString();
    136                                 //负号
    137                                 if (ParseValueIsMinus(strOp))
    138                                 {
    139                                     strOp = strOp.Replace("-", "");
    140 
    141                                     int tempMin = 0;
    142                                     if (Int32.TryParse(strOp, out tempMin))
    143                                     {
    144                                         if (tempMin > Math.Abs(MinNum + 1))
    145                                         {
    146                                             fEditValue = e.OldValue;
    147                                             return;
    148                                         }
    149                                     }
    150                                     else
    151                                     {
    152                                         fEditValue = e.OldValue;
    153                                         return;
    154                                     }
    155                                     strOp = "-" + strOp;
    156                                     fEditValue = strOp;
    157                                 }
    158                                 else if (strOp.Contains("-"))//多负号情况
    159                                 {
    160                                     strOp = strOp.Replace("-", "");
    161                                     int tempMax = 0;
    162                                     if (Int32.TryParse(strOp, out tempMax))
    163                                     {
    164                                         if (tempMax > MaxNum)
    165                                         {
    166                                             fEditValue = e.OldValue;
    167                                             return;
    168                                         }
    169                                     }
    170                                     else
    171                                     {
    172                                         fEditValue = e.OldValue;
    173                                         return;
    174                                     }
    175                                     fEditValue = strOp;
    176                                 }
    177                                 else
    178                                     fEditValue = e.OldValue;//还原
    179                                 return;
    180                             }
    181                             if (intNewNum > MaxNum
    182                                 || intNewNum < MinNum)//不在范围里的数据
    183                             {
    184                                 fEditValue = e.OldValue;
    185                                 return;
    186                             }
    187                             //同步设置新值
    188                             fEditValue = e.NewValue;
    189                         }
    190                         else
    191                         {
    192                             //同步设置新值(特殊)
    193                             fEditValue = 0;
    194                         }
    195                     } break;
    196                 case ValueType.String:
    197                     {
    198                         fEditValue = e.NewValue;
    199                     } break;
    200                 default:
    201                     {
    202                         fEditValue = e.NewValue;
    203                     } break;
    204 
    205             }
    206         }
    207 
    208         /// <summary>
    209         /// 值改变后事件
    210         /// </summary>
    211         /// <param name="e"></param>
    212         protected override void OnTextChanged(EventArgs e)
    213         {
    214             if (this.Text != null)
    215                 this.SelectionStart = this.Text.Length;
    216 
    217             if (this.Text.Equals(EditValue))
    218             {
    219                 return;
    220             }
    221 
    222             base.OnTextChanged(e);
    223             EditValue = this.Text;
    224         }
    225 
    226         /// <summary>
    227         /// 调用注册的事件
    228         /// </summary>
    229         /// <param name="e"></param>
    230         public void ReiseEditValueChanging(ChangingEventArgs e)
    231         {
    232             ChangingEventHandler handler = (ChangingEventHandler)this.Events[editValueChanging];
    233             if (handler != null) handler(this, e);
    234         }
    235         #endregion
    236 
    237         #region 内部方法
    238         /// <summary>
    239         /// 判断字符串是否是负数
    240         /// </summary>
    241         /// <param name="strOp"></param>
    242         /// <returns></returns>
    243         private bool ParseValueIsMinus(string strOp)
    244         {
    245             bool blReturn = false;
    246 
    247             int index = strOp.IndexOf('-');
    248             if (index >= 0)
    249             {
    250                 index = strOp.IndexOf('-', index + 1);
    251                 if (index < 0)
    252                     blReturn = true;
    253             }
    254             return blReturn;
    255         }
    256         #endregion
    257 
    258 
    259         #region 枚举
    260         /// <summary>
    261         /// 改变值类型
    262         /// </summary>
    263         public enum ValueType
    264         {
    265             Number,
    266             String,
    267         } 
    268         #endregion
    269     }
    270 }
    View Code

    使用

    由于是控件,所以没有采用UnitTest方式,而是建立一个winfrom窗体进行测试。

    定义2个控件

    texBoxEx1 字符串输入

    tbxBoxEx2 数字型输入,最小值-200,最大值200

    代码做了简单过滤

     1         private void textBoxEx1_EditValueChanging(object sender, ControlsEx.ChangingEventArgs e)
     2         {
     3             //简单的过滤abc和100
     4             if (e.NewValue.ToString() == "abc")
     5                 e.Cancel = true;
     6         }
     7 
     8         private void textBoxEx2_EditValueChanging(object sender, ControlsEx.ChangingEventArgs e)
     9         {
    10             //简单的过滤100
    11             int temp = (int)e.NewValue;
    12             if (temp == 100)
    13                 e.Cancel = true;
    14         }
    View Code

    测试结果如下:

    对于tbxBoxEx1的输入abc,在输入c的时候就输入不进去了,换个d就可以输入进去了。

    对于tbxBoxEx2,在输入-201的时候不能输入,201的时候也不能,100的时候也不能。由于验证机制是调用订阅的验证机制然后才是基类的验证机制,所以订阅的是做扩展用的。所以订阅的代码还是要做点异常处理,比如输入其他字符号。当时想的是默认情况下基类判断起作用,如果想做扩展,订阅这个事件,然后处理,但是现在过了这多年回来看,这块还是需要优化下,应该为了更方便的点,基类的判断应该是一直前的,这样可以少了很多异常判断,所以这里测试代码就简单的过滤100就行了,负数等的自行取消订阅事件里的代码。

    GitHub

    https://github.com/sinodzh/ControlsEx

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。

    文章是哥(mephisto)写的,SourceLink

  • 相关阅读:
    在 《超过 光速 的 方法》 里 的 回复
    超过 光速 的 方法
    在 《我对 相对论 提出了一个 修正,名为 “K氏修正”》 里 的 回复
    我对 相对论 提出了一个 修正,名为 “K氏修正”
    input 只读不能修改
    获取父iframe的高宽
    indexOf ie下的兼容问题
    英文单词自动换行
    textarea 限制字数
    js判断输入框的范围,并且只能输入数字
  • 原文地址:https://www.cnblogs.com/mephisto/p/4355301.html
Copyright © 2020-2023  润新知