开发者社区> 夏春涛> 正文

ASP.NET自定义控件开发--微调控件(NumericUpDown)

简介:      闲来无事,学习了下红皮书《ASP.NET组件工具包》中第1章“微调控件”,将其VB.NET代码改写为C#代码,并作了较详细的注释,实现了一个类似WinForm中NumericUpDown的微调控件。
+关注继续查看

  
  闲来无事,学习了下红皮书《ASP.NET组件工具包》中第1章“微调控件”,将其VB.NET代码改写为C#代码,并作了较详细的注释,实现了一个类似WinForm中NumericUpDown的微调控件。

  效果图如右:

  先总结一下开发中的问题和经验:

  1.注意:将控件项目的“属性”-->“通用属性”-->“常规”中的“默认命名空间”设为空,否则总出现错误:“System.ArgumentException: 已存在具有相同键的条目。”

哪位高手知道原因的话请赐教。???

  2.注意:将.js文件和.bmp文件作为嵌入资源进行编译。方法:在“解决方案资源管理器”中选中文件,右键“属性”,在属性框中“生成操作”项中选择“嵌入的资源”,随后编译该项目即可。

  3.注意:.bmp文件是作为控件的自定义图标显示在工具箱中的(如果你把控件添加到工具箱中的话),该文件要求必须与控件同名(如本程序中的命名为:Xct.WebControls.Spinner.bmp),且带.bmp后缀。

  4.将控件添加到工具箱中的方法:VS2003-IDE菜单“工具”-->“添加/移除工具箱项...”,在“.NET Framework组件”选项卡中点击“浏览”,选择控件对应的dll文件后点击“确定”。在工具箱的“常规”选项卡中就出现新添的控件,如图

 

  5.优点:该控件在编译时将JS脚本资源嵌入到了程序集dll文件中,使得在布暑应用时不需要再拷贝js文件

  6.问题:该控件的属性“TextAlign - 文本对齐方式”不起作用,不知怎么回事。???

  运行环境:Win2003Server + IIS6 + VS2003 + .NET Framework 1.1 + IE6

  附:《ASP.NET组件工具包》书中的代码可以在http://support.apress.com/books.asp?bID=1861008023&s=0下载.(注:在www.wrox.com找不到其源码下载)
  ===============================================================================

  控件程序代码(Spinner.cs):---- 

 

  1using System;
  2using System.Web.UI;
  3using System.Web.UI.WebControls;
  4using System.ComponentModel;
  5using System.IO;
  6
  7
  8//指定控件的标记前缀
  9[assembly: TagPrefix("Xct.WebControls","xct")]
 10namespace Xct.WebControls
 11{
 12    枚举类型#region 枚举类型
 13    /**//// <summary>
 14    /// 滚动箭头的位置,可以在文本框左侧或右侧
 15    /// </summary>

 16    public enum SpinnerAlign
 17    {
 18        Left  = 0,
 19        Right = 1
 20    }

 21
 22    /**//// <summary>
 23    /// 文本框中的文本对齐方式
 24    /// </summary>

 25    public enum ValueAlign
 26    {
 27        Center = 0,
 28        Left   = 1,
 29        Right  = 2
 30    }

 31    #endregion

 32
 33    /**//// <summary>
 34    /// ** 微调控件V1.0 ** (夏春涛 2007-09-26) **
 35    /// </summary>

 36    
 37    [ToolboxData("<{0}:Spinner runat=\"server\" width=\"80px\" buttonsize=\"XX-Small\" />")]
 38    public class Spinner : WebControl, INamingContainer
 39    {
 40        脚本资源变量#region 脚本资源变量
 41        //Scripts变量用于存储脚本资源
 42        private static string Scripts;
 43        //StartupScriptFormat变量用于存储初始化微调控件的脚本资源
 44        private static string StartupScriptFormat = "<script language=\"JavaScript\">t = document.getElementById(\"{0}\"); t.step = {1}; t.original = {2}; t.max = {3}; t.min = {4};</script>";
 45        #endregion

 46
 47        静态构造函数#region 静态构造函数
 48        /**//// <summary>
 49        /// 静态构造函数,从程序集中提取脚本资源字符串,并将之存入Scripts变量
 50        /// </summary>

 51        static Spinner()
 52        {
 53            //获取当前代码正从中运行的 System.Reflection.Assembly
 54            System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
 55
 56            if (asm != null)
 57            {
 58                string resource = "SpinnerLib.js";
 59                Stream stm      = asm.GetManifestResourceStream(resource);//从程序集加载指定的清单资源
 60                if (stm==nullreturn;
 61
 62                try
 63                {
 64                    StreamReader reader = new StreamReader(stm);
 65                    Scripts = reader.ReadToEnd();
 66                    reader.Close();
 67                }

 68                finally
 69                {
 70                    if (stm != null) stm.Close();
 71                }

 72
 73            }

 74        }

 75        #endregion

 76
 77        属性定义#region 属性定义
 78        
 79        Increment - 步长#region Increment - 步长
 80        private int _inc = 1;
 81
 82        [Bindable(true),Category("Data"),DefaultValue(1),Description("步长")]
 83        public int Increment
 84        {
 85            get
 86            {
 87                return _inc;
 88            }

 89
 90            set
 91            {
 92                _inc = value;
 93            }

 94        }

 95        #endregion

 96
 97        Value - 值#region Value - 值
 98        private int _value = 0;
 99
100        [Bindable(true),Category("Appearance"),DefaultValue(0),Description("")]
101        public int Value
102        {
103            get
104            {
105                return _value;
106            }

107
108            set
109            {
110                _value = value;
111                base.ChildControlsCreated = false;                
112            }

113        }

114        #endregion

115
116        Maximum - 最大值#region Maximum - 最大值
117        private int _max = 100;
118
119        [Bindable(true),Category("Data"),DefaultValue(100),Description("最大值")]
120        public int Maximum
121        {
122            get
123            {
124                return _max;
125            }

126
127            set
128            {
129                _max = value;
130            }

131        }

132        #endregion

133        
134        Minimum - 最小值#region Minimum - 最小值
135        private int _min = 0;
136
137        [Bindable(true),Category("Data"),DefaultValue(0),Description("最小值")]
138        public int Minimum
139        {
140            get
141            {
142                return _min;
143            }

144
145            set
146            {
147                _min = value;
148            }

149        }

150        #endregion

151
152        ButtonAlign - 按钮位置#region ButtonAlign - 按钮位置
153        private SpinnerAlign _align = SpinnerAlign.Right;
154
155        [Bindable(true),Category("Layout"),DefaultValue(SpinnerAlign.Right),Description("按钮位置")]
156        public SpinnerAlign ButtonAlign
157        {
158            get
159            {
160                return _align;
161            }

162
163            set
164            {
165                if (!Enum.IsDefined(Type.GetType("Xct.WebControls.SpinnerAlign"),value))
166                    throw new ArgumentException();
167
168                //将基类的ChildControlsCreated设为false,为此需要重写ChildControlsCreated方法,
169                //该方法用于构建组成界面的子控件的层次结构
170                base.ChildControlsCreated = false;
171                _align = value;
172            }

173        }

174        #endregion

175
176        TextAlign - 文本对齐方式#region TextAlign - 文本对齐方式
177        private ValueAlign _textalign = ValueAlign.Right;
178
179        [Bindable(true),Category("Layout"),DefaultValue(ValueAlign.Right),Description("文本对齐方式")]
180        public ValueAlign TextAlign
181        {
182            get
183            {
184                return _textalign;
185            }

186
187            set
188            {
189                if (!Enum.IsDefined(Type.GetType("Xct.WebControls.ValueAlign"),value))
190                    throw new ArgumentException();
191
192                //将基类的ChildControlsCreated设为false,为此需要重写ChildControlsCreated方法,
193                //该方法用于构建组成界面的子控件的层次结构
194                base.ChildControlsCreated = false;
195                _textalign = value;
196            }

197        }

198        #endregion

199
200        ButtonSize - 按钮字体大小#region ButtonSize - 按钮字体大小
201        private FontUnit _size;
202
203        [Bindable(true),Category("Appearance"),Description("按钮字体大小")]
204        public FontUnit ButtonSize
205        {
206            get
207            {
208                return _size;
209            }

210
211            set
212            {
213                base.ChildControlsCreated = false;
214                _size = value;
215            }

216        }

217        #endregion

218
219        #endregion

220        
221        重载ChildControlsCreated方法#region 重载ChildControlsCreated方法
222        //构建组成界面的子控件的层次结构,以便为回发或呈现做准备
223        //当开发复合服务器控件或模板服务器控件时,必须重写此方法
224        protected override void CreateChildControls()
225        {
226            创建表格#region 创建表格
227            Table tb = new Table();
228            TableCell tc;
229
230            tb.CellPadding = 0;
231            tb.CellSpacing = 0;
232
233            tb.Rows.Add(new TableRow());
234            tb.Rows.Add(new TableRow());
235            tb.Rows[0].Cells.Add(new TableCell());
236            tb.Rows[0].Cells.Add(new TableCell());
237            tb.Rows[1].Cells.Add(new TableCell());
238
239            base.Controls.Clear();//清除基类中的控件
240            base.Controls.Add(tb);//添加新创建的表格
241            #endregion

242
243            创建文本框#region 创建文本框
244            TextBox txt = new TextBox();
245            txt.ID = "txtValue";
246            //通过Attributes集合把客户端JS事件处理程序添加到服务器控件
247            txt.Attributes.Add("OnKeyPress","return KeyPressed(event,this)");
248            txt.Attributes.Add("OnKeyUp",   "return KeyUp(this)");
249            txt.Attributes.Add("OnChange",  "return SpinnerChanged(this)");
250            txt.Attributes.Add("OnPaste",   "return SpinnerChanged(this)");
251            //应用样式
252            txt.ApplyStyle(this.ControlStyle);
253            //移除文本框的Border(用表格单元格Border代替)
254            txt.Style.Add("Border-Top",   "none");
255            txt.Style.Add("Border-Right""none");
256            txt.Style.Add("Border-Left",  "none");
257            txt.Style.Add("Border-Bottom","none");
258            txt.Width = new Unit("100%");        //文本框的宽度
259            txt.Text = this.Value.ToString();    //文本框的值
260        
261
262            //设置文本框所在的单元格的样式
263            if (this.ButtonAlign == SpinnerAlign.Left)
264                tc = tb.Rows[0].Cells[1];
265            else
266                tc = tb.Rows[0].Cells[0];
267
268            tc.Style.Add("vertical-align","middle");
269
270            tc.ApplyStyle(this.ControlStyle);
271
272            tc.Style.Add("Border-Top",   "2px inset");
273            tc.Style.Add("Border-Right""silver 1px solid");
274            tc.Style.Add("Border-Left",  "2px inset");
275            tc.Style.Add("Border-Bottom","silver 1px solid");
276            tc.Controls.Add(txt);
277            tc.RowSpan = 2;//使文本框跨越Up/Down按钮两行
278            tc.Width = new Unit("100%");
279            #endregion

280
281            Up按钮#region Up按钮
282            //判断客户端浏览器是不是IE
283            bool isIE = true;
284            try
285            {
286                isIE = Context.Request.Browser.VBScript;
287            }

288            catch
289            {
290                //null
291            }

292
293            //Up按钮的单元格
294            if (this.ButtonAlign == SpinnerAlign.Left)
295                tc = tb.Rows[0].Cells[0];
296            else
297                tc = tb.Rows[0].Cells[1];
298
299            //Up按钮
300            tc.BackColor = System.Drawing.Color.Gainsboro;
301            tc.BorderStyle = (isIE==true ? BorderStyle.Outset : BorderStyle.Solid);
302            tc.BorderWidth = new Unit("1px");
303            tc.Style.Add("cursor""pointer");
304            tc.Font.Size = _size;
305
306            tc.Attributes.Add("OnMouseUp",   "this.style.backgroundColor='Gainsboro';"  + (isIE==true ? "this.style.borderStyle='outset';" : ""));
307            tc.Attributes.Add("OnMouseDown""this.style.backgroundColor='WhiteSmoke';" + (isIE==true ? "this.style.borderStyle='inset';"  : ""));
308            tc.Attributes.Add("OnMouseOut",  "this.style.backgroundColor='Gainsboro';"  + (isIE==true ? "this.style.borderStyle='outset';" : ""));
309            tc.Attributes.Add("OnClick",     "Increment('" + txt.ClientID + "');");
310            tc.Text = "";//字符"▲".
311            #endregion

312
313            Down按钮#region Down按钮
314            tc = tb.Rows[1].Cells[0];
315            tc.BackColor = System.Drawing.Color.Gainsboro;
316            tc.BorderStyle = (isIE==true ? BorderStyle.Outset : BorderStyle.Solid);
317            tc.BorderWidth = new Unit("1px");
318            tc.Style.Add("cursor""pointer");
319            tc.Font.Size = _size;
320
321            tc.Attributes.Add("OnMouseUp",   "this.style.backgroundColor='Gainsboro';"  + (isIE==true ? "this.style.borderStyle='outset';" : ""));
322            tc.Attributes.Add("OnMouseDown""this.style.backgroundColor='WhiteSmoke';" + (isIE==true ? "this.style.borderStyle='inset';"  : ""));
323            tc.Attributes.Add("OnMouseOut",  "this.style.backgroundColor='Gainsboro';"  + (isIE==true ? "this.style.borderStyle='outset';" : ""));
324            tc.Attributes.Add("OnClick",     "Decrement('" + txt.ClientID + "');");
325
326            tc.Text = "";//字符"▼"
327            #endregion

328
329        }

330
331        #endregion

332
333        重载AddAttributesToRender#region 重载AddAttributesToRender
334        //将需要呈现的 HTML 属性和样式添加到指定的 HtmlTextWriterTag 中。此方法主要由控件开发人员使用
335        protected override void AddAttributesToRender(HtmlTextWriter writer)
336        {
337            //请注意TextBox控件的宽度被指定为100%,所以如果省略下步控件的宽度会覆盖整个页面
338            writer.AddStyleAttribute(HtmlTextWriterStyle.Width,this.Width.ToString());//默认宽度80px
339        }

340        #endregion

341
342        重载OnPreRender#region 重载OnPreRender
343        //此方法通知服务器控件在保存视图状态和呈现内容之前,执行任何必要的预呈现步骤
344        protected override void OnPreRender(EventArgs e)
345        {
346            EnsureChildControls();//确定服务器控件是否包含子控件。如果不包含,则创建子控件。
347            base.OnPreRender (e);
348        }

349        #endregion

350
351        重载Render#region 重载Render
352        //将服务器控件内容发送到提供的 HtmlTextWriter 对象,此对象编写将在客户端呈现的内容
353        //在开发自定义服务器控件时,可以重写此方法以生成 ASP.NET 页的内容
354        protected override void Render(HtmlTextWriter writer)
355        {
356            EnsureChildControls();//确定服务器控件是否包含子控件。如果不包含,则创建子控件。
357            base.Render(writer);
358        }

359        #endregion

360
361        重载OnLoad,向客户端发送JS脚本资源#region 重载OnLoad,向客户端发送JS脚本资源
362        protected override void OnLoad(EventArgs e)
363        {
364            EnsureChildControls();//确定服务器控件是否包含子控件。如果不包含,则创建子控件。
365            
366            
367            //注册脚本库
368            if (!Page.IsClientScriptBlockRegistered(this.GetType().FullName))
369            {
370                Page.RegisterClientScriptBlock(this.GetType().FullName, Scripts);
371            }

372
373               Page.RegisterStartupScript(this.ClientID, String.Format( StartupScriptFormat, 
374                                                                         this.FindControl("txtValue").ClientID, 
375                                                                         this.Increment, 
376                                                                         this.Value, 
377                                                                         this.Maximum, 
378                                                                         this.Minimum
379                                                                        )
380                                          );
381
382            base.OnLoad (e);
383        }

384        #endregion

385
386
387    }

388}

389

 

 

  Javascript脚本源码(SpinnerLib.js, 这是原书附带的代码):---- 

 

 1<script language="JavaScript">
 2<!--
 3  function IsChar(code)
 4  {
 5    return /\w/.test(String.fromCharCode(code));
 6  }

 7  function KeyPressed(e, src)
 8  {
 9    var code;
10
11    if (e.which == undefined)
12    {
13      //IE
14      code = e.keyCode;
15    }

16    else
17    {
18      //Mozilla/NS6+
19      code = e.which;
20    }

21
22    // It's not a character value, leave the function.
23    if (!IsChar(code)) return true;
24    
25    return !isNaN(String.fromCharCode(code));
26  }

27  function KeyUp(src)
28  {
29    // If we have a valid value, we save it for later,
30    // else we restore the previously saved value.
31    if (src.value <= src.max && src.value >= src.min)
32    {
33      src.original = src.value;
34      return true;
35    }

36    else
37    {
38      // Exceptional case: the user is entering a negative number.
39      if (src.value == "-"return true;
40
41      src.value = src.original;
42      return false;
43    }

44  }

45  function SpinnerChanged(src)
46  {
47    // If we have a valid value, we save it for later,
48    // else we restore the previously saved value.
49    if (src.value <= src.max && src.value >= src.min)
50    {
51      src.original = src.value;
52      return true;
53    }

54    else
55    {
56      src.value = src.original;
57      return false;
58    }

59  }

60
61  function Decrement(target)
62  {
63    src = document.getElementById(target);
64    src.value = parseInt(src.value) - parseInt(src.step);
65    SpinnerChanged(src);
66    src.focus();
67  }

68
69  function Increment(target)
70  {
71    src = document.getElementById(target);
72    src.value = parseInt(src.value) + parseInt(src.step);
73    SpinnerChanged(src);
74    src.focus();
75  }

76//-->
77</script>
78
79

 

  完整程序文件下载:----/Files/bluesky521/Spinner_OK200709271300.rar


  ---- 作者:夏春涛 Email:xchuntao@163.com QQ:23106676



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
基于Asp.Net Mvc开发的个人博客系统
一个基于Mvc 5构建的简单、代码层级分明的开源个人博客系统。前端美观大气、后台采用RightControl .NET通用角色权限系统,开发简单、效率高。网站配置采用XML配置,灵活可以根据自己是需求进行个性化配置。系统功能完备,完全可以满足需求,基本不用二次开发,非常使用程序员的个人博客。
53 0
CentOS开发ASP.NET Core入门教程
原文:CentOS开发ASP.NET Core入门教程 作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9891346.html 因为之前一直没怎么玩过CentOS,大多数时间都是使用Win10进行开发,然后程序都部署在Window Server2008或者Window Server2012上!因此想尝试下Linux系统。
1204 0
基于ASP.Net Core 开发的纯BS结构的RoadFlow工作流平台
RoadFlow是一款集成工作流引擎的ASP.NET CORE MVC快速开发框架
3439 0
用VSCode开发一个asp.net core2.0+angular5项目(5): Angular5+asp.net core 2.0 web api文件上传
第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 第三部分: https://www.
1356 0
用VSCode开发一个asp.net core 2.0+angular 5项目(4): Angular5全局错误处理
第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 第三部分: https://www.
1619 0
ASP.NET自定义控件组件开发 第五章 模板控件开发
原文:ASP.NET自定义控件组件开发 第五章 模板控件开发                                                                                         第五章 模板控件开发   系列文章链接: ASP.
912 0
ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl
原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl                                              第四章 组合控件开发CompositeControl             大家好,今天我们来实现一个自定义的控件,之前我们已经知道了,要开发自定义的控件一般继承三个基 类:Control,WebControl,还有一个就是今天要说的CompositeControl。
928 0
+关注
夏春涛
曾任教于信息工程大学16年,长期从事计算机软件与信息安全教学科研工作,目前任职于某软件公司从事技术管理工作,擅长架构设计、开发管理,对大数据、分布式颇感兴趣。
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载