本文版权归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. luogg_java学习_04_数组

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! 数组 数组是多个相同类型数据的组合 //1.定义数组 ...

  2. Phar与Composer

    如果你想把PHP玩出像Java那样的花来,那Phar.Composer甚至Phing应该都是必须要玩一遍的. Phar - Php Archive.包管理器,有些类似Java中的jar包,但有所不同. ...

  3. 求助,eclipse总是卡在building workspace-CSDN论坛

    1).解决方法 方法1.修改eclipse启动文件 eclipse.ini 中添加启动参数参数: -vmargs -Xmx512m 方法2.关闭自动构建工作区: project -> build ...

  4. 优化加载jQuery的方法

    请看下面的一段代码: <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js" ...

  5. 【转】MyEclipse快捷键大全

    常用快捷键 -------------------------------------MyEclipse 快捷键1(CTRL)------------------------------------- ...

  6. Git基本使用教程

    1.创建版本库      版本库又可以称为仓库(repository),可以简单理解为一个目录,在这个目录下的所有文件都可以被git管理起来,每个文件的新增.修改.删除Git都可以跟踪,以便在任何时刻 ...

  7. 推荐12个最好的 JavaScript 图形绘制库

    众多周知,图形和图表要比文本更具表现力和说服力.图表是数据图形化的表示,通过形象的图表来展示数据,比如条形图,折线图,饼图等等.可视化图表可以帮助开发者更容易理解复杂的数据,提高生产的效率和 Web  ...

  8. Julius JS – 最流行的网页语音识别库

    JuliusJS 是用于在网页中的语音识别库.这是 Julius(由日本京都大学和日本IPA联合开发的一个实用高效双通道的大词汇连续语音识别引擎)的 JavaScript 实现.它实时侦听用户的语音并 ...

  9. 百度地图API使用方法详解

    最近做了个项目,其中项目中有个需求需要用到百度地图进行导航,通过查阅相关资料参考百度地图api完成了一个例子. API地址:http://developer.baidu.com/map/jsdemo. ...

  10. SVN源码泄露漏洞

    SVN(subversion)是源代码版本管理软件,造成SVN源代码漏洞的主要原因是管理员操作不规范.“在使用SVN管理本地代码过程中,会自动生成一个名为.svn的隐藏文件夹,其中包含重要的源代码信息 ...