本文版权归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所需的数据结构。

     /// <summary>
/// 正在改变EventArgs
/// </summary>
public class ChangingEventArgs : CancelEventArgs
{
private object newValue;
private object oldValue; /// <summary>
/// 正在改变EventArgs
/// </summary>
/// <param name="oldValue">原值</param>
/// <param name="newValue">新值</param>
public ChangingEventArgs(object oldValue, object newValue)
: this(oldValue, newValue, false)
{
} /// <summary>
/// 正在改变EventArgs
/// </summary>
/// <param name="oldValue">原值</param>
/// <param name="newValue">新值</param>
/// <param name="cancel">是否取消</param>
public ChangingEventArgs(object oldValue, object newValue, bool cancel)
: base(cancel)
{
this.oldValue = oldValue;
this.newValue = newValue;
} /// <summary>
/// 新值
/// </summary>
public object NewValue
{
get
{
return this.newValue;
}
set
{
this.newValue = value;
}
} /// <summary>
/// 原值
/// </summary>
public object OldValue
{
get
{
return this.oldValue;
}
}
}

二:TextBoxEx控件

     提供扩展的textbox功能。

1.委托及事件定义

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

         /// <summary>
/// 改变中事件句柄
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void ChangingEventHandler(object sender, ChangingEventArgs e); /// <summary>
/// <para>值改变中事件
/// </para>
/// </summary>
[Description("值改变中事件"), Category("事件")]
public event ChangingEventHandler EditValueChanging
{
add
{
base.Events.AddHandler(editValueChanging, value);
}
remove
{
base.Events.RemoveHandler(editValueChanging, value);
}
}

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

         /// <summary>
/// 输入的最大值
/// </summary>
[Description("输入的最大值")]
public Int32 MaxNum
{
get { return _maxNum; }
set { _maxNum = value; }
}
/// <summary>
/// 输入的最小值
/// </summary>
[Description("输入的最小值")]
public Int32 MinNum
{
get { return _minNum; }
set
{
if (value <= )
_minNum = value;
}
}
/// <summary>
/// 输入值类型
/// </summary>
[Description("输入值类型")]
public ValueType EditValueType
{
get { return _editValueType; }
set
{
_editValueType = value;
//设置初始值
if (value == ValueType.Number)
{
EditValue = ;
}
else
EditValue = null;
}
}

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

     public class TextBoxEx:TextBox
{
#region 委托
/// <summary>
/// 改变中事件句柄
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void ChangingEventHandler(object sender, ChangingEventArgs e);
#endregion #region 参数
private Int32 _maxNum = Int32.MaxValue;//最大值
private Int32 _minNum = Int32.MinValue;//最小值
private ValueType _editValueType = ValueType.String;
private static readonly object editValueChanging = new object();//EditValueChanging事件对应的Key
#endregion #region Protected 参数
/// <summary>
/// 编制值
/// </summary>
protected object fEditValue = null;
/// <summary>
/// 编辑原始值
/// </summary>
protected object fOldEditValue = null;
#endregion #region 公有属性
/// <summary>
/// 输入的最大值
/// </summary>
[Description("输入的最大值")]
public Int32 MaxNum
{
get { return _maxNum; }
set { _maxNum = value; }
}
/// <summary>
/// 输入的最小值
/// </summary>
[Description("输入的最小值")]
public Int32 MinNum
{
get { return _minNum; }
set
{
if (value <= )
_minNum = value;
}
}
/// <summary>
/// 输入值类型
/// </summary>
[Description("输入值类型")]
public ValueType EditValueType
{
get { return _editValueType; }
set
{
_editValueType = value;
//设置初始值
if (value == ValueType.Number)
{
EditValue = ;
}
else
EditValue = null;
}
} #endregion #region 事件属性
/// <summary>
/// <para>值改变中事件
/// </para>
/// </summary>
[Description("值改变中事件"), Category("事件")]
public event ChangingEventHandler EditValueChanging
{
add
{
base.Events.AddHandler(editValueChanging, value);
}
remove
{
base.Events.RemoveHandler(editValueChanging, value);
}
}
#endregion #region 私有属性
/// <summary>
/// 编辑值
/// </summary>
private object EditValue
{
get { return fEditValue; }
set
{
if (EditValue == value) return;
OnEditValueChanging(new ChangingEventArgs(fEditValue, value));
this.Text = fEditValue == null ? null : fEditValue.ToString();
}
}
#endregion #region 事件
/// <summary>
/// 编辑值正在改变事件
/// </summary>
/// <param name="e"></param>
protected virtual void OnEditValueChanging(ChangingEventArgs e)
{
//调用注册的事件
ReiseEditValueChanging(e); if (e.Cancel)//注册的事件取消 还原值
{
fEditValue = e.OldValue;
return;
} switch (_editValueType)
{
case ValueType.Number://数值类型
{
if (e.NewValue != null && !string.IsNullOrEmpty(e.NewValue.ToString()))//非空值
{
int intNewNum = ;
if (!Int32.TryParse(e.NewValue.ToString(), out intNewNum))//非数字
{
string strOp = e.NewValue.ToString();
//负号
if (ParseValueIsMinus(strOp))
{
strOp = strOp.Replace("-", ""); int tempMin = ;
if (Int32.TryParse(strOp, out tempMin))
{
if (tempMin > Math.Abs(MinNum + ))
{
fEditValue = e.OldValue;
return;
}
}
else
{
fEditValue = e.OldValue;
return;
}
strOp = "-" + strOp;
fEditValue = strOp;
}
else if (strOp.Contains("-"))//多负号情况
{
strOp = strOp.Replace("-", "");
int tempMax = ;
if (Int32.TryParse(strOp, out tempMax))
{
if (tempMax > MaxNum)
{
fEditValue = e.OldValue;
return;
}
}
else
{
fEditValue = e.OldValue;
return;
}
fEditValue = strOp;
}
else
fEditValue = e.OldValue;//还原
return;
}
if (intNewNum > MaxNum
|| intNewNum < MinNum)//不在范围里的数据
{
fEditValue = e.OldValue;
return;
}
//同步设置新值
fEditValue = e.NewValue;
}
else
{
//同步设置新值(特殊)
fEditValue = ;
}
} break;
case ValueType.String:
{
fEditValue = e.NewValue;
} break;
default:
{
fEditValue = e.NewValue;
} break; }
} /// <summary>
/// 值改变后事件
/// </summary>
/// <param name="e"></param>
protected override void OnTextChanged(EventArgs e)
{
if (this.Text != null)
this.SelectionStart = this.Text.Length; if (this.Text.Equals(EditValue))
{
return;
} base.OnTextChanged(e);
EditValue = this.Text;
} /// <summary>
/// 调用注册的事件
/// </summary>
/// <param name="e"></param>
public void ReiseEditValueChanging(ChangingEventArgs e)
{
ChangingEventHandler handler = (ChangingEventHandler)this.Events[editValueChanging];
if (handler != null) handler(this, e);
}
#endregion #region 内部方法
/// <summary>
/// 判断字符串是否是负数
/// </summary>
/// <param name="strOp"></param>
/// <returns></returns>
private bool ParseValueIsMinus(string strOp)
{
bool blReturn = false; int index = strOp.IndexOf('-');
if (index >= )
{
index = strOp.IndexOf('-', index + );
if (index < )
blReturn = true;
}
return blReturn;
}
#endregion #region 枚举
/// <summary>
/// 改变值类型
/// </summary>
public enum ValueType
{
Number,
String,
}
#endregion
}
}

使用

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

定义2个控件

texBoxEx1 字符串输入

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

代码做了简单过滤

         private void textBoxEx1_EditValueChanging(object sender, ControlsEx.ChangingEventArgs e)
{
//简单的过滤abc和100
if (e.NewValue.ToString() == "abc")
e.Cancel = true;
} private void textBoxEx2_EditValueChanging(object sender, ControlsEx.ChangingEventArgs e)
{
//简单的过滤100
int temp = (int)e.NewValue;
if (temp == )
e.Cancel = true;
}

测试结果如下:

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

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

GitHub

https://github.com/sinodzh/ControlsEx

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

文章是哥(mephisto)写的,SourceLink

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

  1. 用MVC的辅助方法自定义了两个控件:“可编辑的下拉框控件”和“文本框日历控件”

    接触MVC也没多长时间,一开始学的时候绝得MVC结构比较清晰.后来入了门具体操作下来感觉MVC控件怎么这么少还不可以像ASP.net form那样拖拽.这样设计界面来,想我种以前没学过JS,Jquer ...

  2. ASP.NET中页面加载时文本框(texbox控件)内有文字获得焦点时文字消失

    代码如下: <asp:TextBox ID="TextBox1" runat="server" Height="26px" MaxLe ...

  3. ListView使用自定义适配器的情况下实现适配器的文本和图标控件点击事件执行Activity界面中的方法

    ListView使用的是自定义适配器,列表项的布局文件中含有文本和图标,实现文本区域和图标区域的点击事件. 实现思路:在自定义适配器MyArrayAdapter 类型中自定义接口和接口方法,分别设置文 ...

  4. win32: 文本编辑框(Edit)控件响应事件

    过去几年,关于文本编辑框(Edit)控件的响应事件,我都是在主程序 while(GetMessage(&messages, NULL, 0, 0)) { ... } 捕获. 总感觉这种方式让人 ...

  5. WPF自定义控件(三)の扩展控件

    扩展控件,顾名思义就是对已有的控件进行扩展,一般继承于已有的原生控件,不排除继承于自定义的控件,不过这样做意义不大,因为既然都自定义了,为什么不一步到位呢,有些不同的需求也可以通过此来完成,不过类似于 ...

  6. C# 常用控件及单击事件

    1.窗体 1.常用属性 (1)Name属性:用来获取或设置窗体的名称,在应用程序中可通过Name属性来引用窗体. (2)WindowState属性: 用来获取或设置窗体的窗口状态. 取值有三种: No ...

  7. Android文字跑马灯控件(文本自动滚动控件)

    最近在开发一个应用,需要用到文本的跑马灯效果,图省事,在网上找,但老半天都找不到,后来自己写了一个,很简单,代码如下: import android.content.Context; import a ...

  8. 自己用js写的两个日历控件

    前一阵写了两个日历控件,做了简单的封装,发出来共朋友们参考. 第一个日历控件,条状的日历. (使用方法:调用initBarTime(id,evn),第一个参数是要渲染div的id,第二个参数是点击日期 ...

  9. VC/MFC 工具栏上动态添加组合框等控件的方法

    引言 工具条作为大多数标准的Windows应用程序的一个重要组成部分,使其成为促进人机界面友好的一个重要工具.通过工具条极大方便了用户对程序的操作,但是在由Microsoft Visual C++开发 ...

随机推荐

  1. Spring注解@Value的用法

    有时候我们在配置文件中使用配置的信息不仅需要在xml文件中使用,还可能在类中使用,这个时候,我们可使用@Value注解了: @Value("${rest.service.url}" ...

  2. 由select * from table where 1=1中的1=1说开数据库

    众多网站都有select * from table where 1=1此类语句的介绍,并且,针对该类语句,讲得实在是让人越看越迷茫(一个抄袭一个的,简直不像话),不知道是在说什么,导致很多新手不得要领 ...

  3. python 学习笔记5(深浅拷贝与集合)

    拷贝 我们已经详细了解了变量赋值的过程.对于复杂的数据结构来说,赋值就等于完全共享了资源,一个值的改变会完全被另一个值共享. 然而有的时候,我们偏偏需要将一份数据的原始内容保留一份,再去处理数据,这个 ...

  4. excel查看VBA代码快捷键

    公司现在的很多自动化代码生成使用excel VBA,本来这事跟自己一点关系打不着,不过计划年底切换中间件,这得导致部分代码结构调整,自己还得去调整测试,老忘掉这快捷键,特记录下,Alt + F11

  5. java RSA加解密以及用途

    在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证.对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每 ...

  6. IO流(二)__BufferedReader和BufferedWriter

    BufferedReader和BufferedWriter 字符流的缓冲区:缓冲区的而出现提高了对数据的读写效率对应类:BufferedWriter  BufferedReader缓冲区要结合流才可以 ...

  7. 对chain.doFilter(request,response)的理解

    他的作用是将请求转发给过滤器链上下一个对象.这里的“下”指的是哪里 ? 指的是下一个filter,如果没有filter那就是你请求的资源. 一般filter都是一个链,web.xml 里面配置了几个就 ...

  8. nginx 在ubuntu 上的启动,停止,重启

    vi 显示行号 :set num 在开始玩nginx之前,得先安装nginx,可以参考 <ubuntu15.10_x64 安装 nginx>   启动 sudo /usr/local/ng ...

  9. Error: Error setting TTL index on collection : sessions

    Error: Error setting TTL index on collection : sessions 一.步骤一: 这个问题一般是直接升级 mongodb和connect-mongo的版本为 ...

  10. 提升手持设备点击速度之touch事件带来的坑!

    前言 上周六,我将我们项目的click换成了tap事件,于是此事如梦魇一般折磨了我一星期!!! 经过我前仆后继的努力,不计代价的牺牲,不断的埋坑填坑,再埋坑的动作,最后悲伤的发现touch事件确实是个 ...