----ASP.net开发系列内容介绍

----ASP.net开发系列内容介绍

今天你写控件了吗?----ASP.net控件开发系列之开篇

早段时间,同事之间很流行打CS,所以那段时间的问候变成了“今天你杀XX了吗?”
控 件开发也许是程序员最能发掘自己创造力的一件事情吧?控件开发不仅要求你对当前的开发有一个较全面和略深的了解,而且也能促使你去了解开发环境的底层的东 西。比方说我在开发控件的过程中就对reflect和MSIL产生了较深的兴趣,也许,在以后的一段时间里,我会尝试去做一个reflector,哈哈, 很多事情都很难说地~
“今天你写控件了吗?”,也许在将来会成为中国.net程序员的一个日常用语,哈哈,很多事情都很难说地~不好意思,重复了一下,毕竟,在.net的框架 下一些简单的控件的开发相对来说,是·很·容易的。.net框架已经为你做了大部分的事(当然,我这种说法是有误的,创新永远是第一位的。),我所做,只 是想凭自己三寸烂舌和一股热情,告诉大家,那个真的很容易。
现在,你有信心了吗?

在这开篇,我还想和大家探讨几个问题?

1.ASP.net是ASP+吗?
记得有这么一句话,微软喜欢给一些换汤不换药的东西换一个全新的名字,让人认为是一种全新的技术,而有些完全不同的东西却整一个很相像的名字, ASP.net和ASP就是这样,ADO.net和ADO.net更是这样。在这里,我想说的是,ASP.net和ASP是很不相同的。ASP是建立在 WINDOW DNA上的(这句也许有误,我对旧的技术没什么底蕴),以解释为执行方式的,而ASP.net是建立在.net framework这一全新的东东上的,是先编译后运行的,所以ASP.net的效率更高,而且有.net framework的支持,可以做很多很多的功能,而且很方便,你不必在COM的世界为了一个功能大海捞针,在一个统一的.net环境中写写代码就OK 了,同时,Web serviceS做为它的同胞,和asp.net有很大的相通性,你可以很方便的同时为Internet提供基于浏览器和各种客户端GUI程序的服务,还 有remoting.....爽歪了啊!

2.ASP.net都做了什么?
ASP.net是怎么生成一个个活蹦乱跳的鲜活网页的呢?IIS做为一个HOST,为一个个ASP.net程序创建AppDomain而不是一个个 Process,每个ASP.net程序在第一次运行时被编译为机器码,为客户的Request生成Response。我们在制作网页的时候,.aspx 文件和.aspx.cs文件好像各占半壁江山,而其实的页的生成过成中,.aspx文件中的东西只是Render方法的一串Write调用。

3.ASP.net开发,我们的重点该放在哪呢?
是啊,我们的重点该放在哪哟?我重点培养自己哪方面的技能呢?在上一点中,我说.aspx文件只不是后台程序的一个方法(Render)中的部分而已,那 么意思是不是前台的东西就只是一个狗屁呢?对这个观点,我是坚绝反对的,理由有:第一、ASP.net最终还是用HTML、Script、CSS来实现界 面,完成功能。一个Render而已,可这个Render可了不得啊,ASP.net中大部分的东西最终不就是为了这个Render吗?第二、.net框 架已经为我们做了太多太多的东西,我们可以很舒服的完成我们需要的功能,用System.Drawing画出有水印的图,用System.Data玩把戏 般的操作数据,正则?XML?......一切都有一堆积木在那等着你堆了。所以,我们前进的道路很清晰的两路,就是,用那些老掉牙的 DHMTL/JS/CSS技术完成你的创意,另一方法,努力学习软件开发的方法论,什么模式、什么UML、什么框架、什么用例、什么MDA、什么 AOP......不好意思,接不下去了,吹概念不是我的长处。而且在控件开发中,你没有DHTML这些东西的基础,而以为对现有控件的深度发展就能做出 一个很成功的控件和创意出来?基本上......这个(读的时候这里顿一下)很难!

4.Attribute?
Attribute? 这个是.net中很重要的概念,在控件开发在尤其重要。很多书都说Attribute和Property不好分别,我的理解很简单,Property是内 在的属性,Attribute是相对“外在”的东西,举个例子,你的肚腩很大这是Property,然后你穿一件很宽松的衣,这是Attribute,当 然这个解释是绝对不正确的,也许“你肚腩很大”这句描述性的话是Attribute那来得正确,不过,这个有助于你理解两者的区别是如此的大,那么这两者 到底是什么呢?其实大家都知道了,我这里再八婆一下。编译器在把你的代码整成一个Assemble时,把Method、Property这些东西整成IL 指令,同时,它会弄出一份描述你的类,方法,属性,字段等等的各种信息的MetaData,所以,在IDE中,我写一个XX.在打下这个点后,后面一堆让 我爱得不得了的智能完成东东就出来了,这些就是MetaData和Reflect的功劳,此外还有VS.net的对象浏览器,某些兄弟偷看我发布的控件的 内部代码的工具,都得益于这个东东,而且IDE也利用反射读取MetaData来决定怎样在设计器如何让用户和控件交互。而!Attribute就是我们 操作MetaData的工具。

......还有呢?暂时没想到,呵呵。

所以,想尝试做控件的兄弟,你不仅要有信心,你还要准备一点HTML/JS/CSS之类的基础和对Attribute等.net的特性的一些了解。你准备好了吗?

也许是年龄的原因,所以我这个人现在做事一般不是很沉稳,所以你在以上一段吹水中找出几个错误我一点也不会吃惊,同时,我很感激你。

今天你写控件了吗?----ASP.net控件开发系列之(二)

“生死有序”
“装装孙子”
上篇文章《开篇》说了不少空洞的理论,这篇文章我还是先说说“大而化之”的东西:1、ASP.net控件(包括页面本身)的生命期的细节;2、如何开始一个控件的编写。
“生死有序”
ASP.net处理程序在接收到一个用户的页面请求后,它是如何变戏法把一个鲜活的页面呈现给客户端的呢?它都做了哪些事?按什么顺序做的?
要说明这个问题,我们首先要明白,一个页面它本身也是一个Control。从设计模式的角度讲,页面模型是一个“合成模式(Composite)”,它本 身是一棵由多层控件组成的结构树,顶层是Page,以下有叶有树枝,叶是不再包涵子控件的控件,枝是又包涵子控件的控件,每一层控件的生成都会调用一个生 成子控件的方法,父控件调用子控件的生成方法,子又调用孙的,如此递归,保证页面中所有有效的(一般情况下是Visible=true)控件都得到生成过 程处理,(有关设计模式的东西大家可以查看吕震宇老师在博客园的设计模式系列文章,该系列文章是对阎博士《Java与模式》一书(88元,很厚)的提炼与 加工,至少可用来做设计模式浅层面速成的教材),而每个控件在生命周期大体都包括以下几个步骤:

----ASP.net开发系列内容介绍

1.实例化(Instantiate)
我们写控件一般不要接触此活动。
2.初始化(Initialize)
同上。
3.跟踪视图(Tracking View State)*
这个比较重要,涉及到视图状态,一般情况下不必重载此方法。
4.加载视图状态(Load view state)*
只会在回传过程中调用此方法,用法同上。
5.加载回传数据(Load postback data)*
如果你的控件生成之后要和客户端交互,那么这个方法就很重要,只会在回传过程中调用此方法。
6.开始载入(Load)
这个活动一般只是Page的OnLoad才会要去管它,我们写控件一般不要接触此方法。
7.有修改(Raise changed events)*
控件生成后,数据被客户端更改过,和加载回传数据是一路的。
8.回传事件处理(Raise postback event)*
一般用于实现IPostBackEventHandler接口的控件的把客户端事件转化成服务器端事件。只用于回传过程。
9.生成预处理(PerRender)**
生成前期工作,这个是很重要的一个过程,通过重载OnPreRender方法实现自定义。
10.保存视图状态(Save view state)*
如果所以信息都是用ViewState[xxx]这种方式来保存,不必重载,只有自定义视图状态管理时才重载此方法,当然,这里做了手脚,LoadViewState也就一定要和这里的Save方法配套。
11.生成(Render)***
这个是主角,控件成生什么东东基本就由这里管了。
12.卸载(Unload)
13.释放(Dispose)
了解控件的生命周期的细节对于我们自定义控件的各个部分以及调试控件,排除控件Bug都是至关重要的。
当然这此过程中有些活动是我们要特别重视的,我在这些活动的后面加了*号。
“装装孙子”
还记得我在上一篇文章中说.net框架已经为我们做了大部分的事情吗?确实,我们写一个控件不是平地起高楼,我们已经有了很多成品和半成品了。很多情况 下,为了快速开发一个控件,你甚至可以使自己的控件直接继承于TextBox、Button之类具体的控件,略做修改,就可实现自己的功能。如果没有这样 的好事,那你也最好考虑从以下两个类继承:System.Web.UI.Control、 System.Web.UI.WebControls.WebControl,第一个类适合于派生生成不是可视HTML对象的控件,如生成< meta><xml>之类内容的控件,第二个类适合于生成各种HTML对象,它已经实现了基本的样式管理、HTML标签生成等等功能。

下一篇打算和大家探讨一下控件属性的方方面面,包括属性与HTML样式的aspx文件文本的关系,属性在VS中的高级编辑方法和在IDE中各种交互方式的定制等等

今天你写控件了吗?----ASP.net控件开发系列(三)

属性全接触(一)

本系列上篇文章有几位抬爱,鼓励了几句,所以劲头又足了,这不,这篇文章就出得快了,:)
希望能继续得到鼓励和指正。
这次我们来探讨下控件开发中的属性设计的方方面面,属性本是各种.net下语言的最基本语法,但控件做为一种提供给程序员二次开发的发布件,其功能的强大与使用的灵活都离不开良好的属性设计,所以我觉得属性设计是控件开发中第一座要打下的堡垒。
首先我们来看一段.aspx文件中的HTML样式的代码:

----ASP.net开发系列内容介绍<asp:DropDownListid="DropDownList1"runat="server"Font-Bold="True">
----ASP.net开发系列内容介绍<asp:ListItemValue="1">1</asp:ListItem>
----ASP.net开发系列内容介绍<asp:ListItemValue="2">2</asp:ListItem>
----ASP.net开发系列内容介绍</asp:DropDownList>
----ASP.net开发系列内容介绍

 

这种代码大家都写过无数次了,不过,现在我们要从另一种角度来分析这段代码:
DropDownList控件在和用户交互时,它没有把它的属性一股脑放在一起来表示出来,而是分为以下几种情况:
1.像ID、Runat、Font-Bold这些,放在<>标记里;
2.Font-Bold不同于其它,它有一个短横分隔成两部分,这种表示方式不是Font-Bold是一个属性的名称,而是说明它是一个子属性,是Font属性(Font类)的Bold属性,对应.cs文件的写法是:Font.Bold;
3.ListItem放在了DropDownList的一双<>标记的中间,而不是标记之类,同样1、2也放在了ListItem的中间。
下面我们来分别看看这几种属性记录方式是怎么实现的。
有一个Attribute来做这件事件PersistenceMode(System.Web.UI.PersistenceModeAttribute)。
它有以下几个值供选择:
Attribute(default)属性保存在控件的标签里;默认值
EnCodedInnerDefaultProperty 属性是编码的HTML,放在控件标签对的中间保存,以上的ListItem就是这样保存Text属性的(1、2);

InnerDefaultProperty 属性保存在控件标签对的中间,以上的DropDownList控件的Items属性就是这样保存的(就是那堆ListItem);

InnerProperty 属性和其它属性一起保存为控件标签对中的嵌套内容,DataGrid用这种方式把一堆东西包在标签里,这时,属性要用标签声明,内含属性值。

----ASP.net开发系列内容介绍[PersistenceMode(PersistenceMode.InnerProperty)]
----ASP.net开发系列内容介绍
publicvirtualTableItemStyleItemStyle
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
get
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍.
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍

 

第二个议题,属性的持久性
众 所周知,网页是基于无状态机制的,就是说,页面Response后就不管理保存页面内容的状态,ASP.net提供ViewState机制来保存页面的状 态,ViewState是实现方式是送出页面中的一个名为__ViewState的input type='hidden',也就是说它和Session不同,它保存在页面中......不废话了,反正我们要保存控件的状态(就是它的各个属性),而 不至于在回传的过程中丢失,我们采用的方案就是ViewState,下面简单的举个例子说明ViewState在Property中的用法

----ASP.net开发系列内容介绍[
----ASP.net开发系列内容介绍DefaultValue(
2),
----ASP.net开发系列内容介绍TypeConverter(
typeof(Int32Converter)),
----ASP.net开发系列内容介绍Category(
"Behavior"),
----ASP.net开发系列内容介绍Description(
"Durationofcompleteoncetransition.(s)")
----ASP.net开发系列内容介绍]
----ASP.net开发系列内容介绍
publicintDuration
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
get
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍
objectb=ViewState["Duration"];
----ASP.net开发系列内容介绍
return(b==null)?2:(int)b;
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍set
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍
if(value<1)
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
thrownewArgumentOutOfRangeException("Duration");
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍ViewState["Duration"]=value;
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍

 

像这种方式直接使用ViewState是最简便的,我们不必改写LoadViewState、SaveViewState方法,至于怎么自定义ViewState管理,在后面的文章中将有介绍。

关于属性的东西太多了,这次就写到这,下篇将写写怎样订制属性与IDE的交互。

今天你写控件了吗?----ASP.net控件开发系列(三)

属性全接触(一)

本系列上篇文章有几位抬爱,鼓励了几句,所以劲头又足了,这不,这篇文章就出得快了,:)
希望能继续得到鼓励和指正。
这次我们来探讨下控件开发中的属性设计的方方面面,属性本是各种.net下语言的最基本语法,但控件做为一种提供给程序员二次开发的发布件,其功能的强大与使用的灵活都离不开良好的属性设计,所以我觉得属性设计是控件开发中第一座要打下的堡垒。
首先我们来看一段.aspx文件中的HTML样式的代码:

----ASP.net开发系列内容介绍<asp:DropDownListid="DropDownList1"runat="server"Font-Bold="True">
----ASP.net开发系列内容介绍<asp:ListItemValue="1">1</asp:ListItem>
----ASP.net开发系列内容介绍<asp:ListItemValue="2">2</asp:ListItem>
----ASP.net开发系列内容介绍</asp:DropDownList>
----ASP.net开发系列内容介绍

 

这种代码大家都写过无数次了,不过,现在我们要从另一种角度来分析这段代码:
DropDownList控件在和用户交互时,它没有把它的属性一股脑放在一起来表示出来,而是分为以下几种情况:
1.像ID、Runat、Font-Bold这些,放在<>标记里;
2.Font-Bold不同于其它,它有一个短横分隔成两部分,这种表示方式不是Font-Bold是一个属性的名称,而是说明它是一个子属性,是Font属性(Font类)的Bold属性,对应.cs文件的写法是:Font.Bold;
3.ListItem放在了DropDownList的一双<>标记的中间,而不是标记之类,同样1、2也放在了ListItem的中间。
下面我们来分别看看这几种属性记录方式是怎么实现的。
有一个Attribute来做这件事件PersistenceMode(System.Web.UI.PersistenceModeAttribute)。
它有以下几个值供选择:
Attribute(default)属性保存在控件的标签里;默认值
EnCodedInnerDefaultProperty 属性是编码的HTML,放在控件标签对的中间保存,以上的ListItem就是这样保存Text属性的(1、2);

InnerDefaultProperty 属性保存在控件标签对的中间,以上的DropDownList控件的Items属性就是这样保存的(就是那堆ListItem);

InnerProperty 属性和其它属性一起保存为控件标签对中的嵌套内容,DataGrid用这种方式把一堆东西包在标签里,这时,属性要用标签声明,内含属性值。

----ASP.net开发系列内容介绍[PersistenceMode(PersistenceMode.InnerProperty)]
----ASP.net开发系列内容介绍
publicvirtualTableItemStyleItemStyle
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
get
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍.
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍

 

第二个议题,属性的持久性
众 所周知,网页是基于无状态机制的,就是说,页面Response后就不管理保存页面内容的状态,ASP.net提供ViewState机制来保存页面的状 态,ViewState是实现方式是送出页面中的一个名为__ViewState的input type='hidden',也就是说它和Session不同,它保存在页面中......不废话了,反正我们要保存控件的状态(就是它的各个属性),而 不至于在回传的过程中丢失,我们采用的方案就是ViewState,下面简单的举个例子说明ViewState在Property中的用法

----ASP.net开发系列内容介绍[
----ASP.net开发系列内容介绍DefaultValue(
2),
----ASP.net开发系列内容介绍TypeConverter(
typeof(Int32Converter)),
----ASP.net开发系列内容介绍Category(
"Behavior"),
----ASP.net开发系列内容介绍Description(
"Durationofcompleteoncetransition.(s)")
----ASP.net开发系列内容介绍]
----ASP.net开发系列内容介绍
publicintDuration
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
get
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍
objectb=ViewState["Duration"];
----ASP.net开发系列内容介绍
return(b==null)?2:(int)b;
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍set
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍
if(value<1)
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
thrownewArgumentOutOfRangeException("Duration");
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍ViewState["Duration"]=value;
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍

 

像这种方式直接使用ViewState是最简便的,我们不必改写LoadViewState、SaveViewState方法,至于怎么自定义ViewState管理,在后面的文章中将有介绍。

关于属性的东西太多了,这次就写到这,下篇将写写怎样订制属性与IDE的交互。

今天你写控件了吗?----ASP.net控件开发系列(五)

TypeConverter

在本系列的上篇文章中,和大家控讨了控件开发与propertyGrid的关系,不知现在大家现在对propertygrid有没有一个较全面的了解,也不知大家有没有做个工程,把propertyGrid拉进去鼓捣鼓捣?

“另起炉灶”


现在我们来思考一个问题:假于,propertygrid没有把属性和事件分成两个分页来显示,会产生什么效果?
那还用说,太乱了。
那如果你设计的控件有很多的属性,而一些关联性很强,或都是操作一个方面的,那么我们可以把它们分门别类,摆到一起,怎么做呢?
我们可以给这个控件类指定以下Attribute:

----ASP.net开发系列内容介绍[PropertyTab(typeof(YourPropertyTab),PropertyTabScope.Component)]
----ASP.net开发系列内容介绍
publicclassYourControlClass
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍

其中,前面一个参数指定处理PropertyTab的类,后一个参数说明要应用在什么时候,Component为当前组件专用,Document当前文档专用,Global只能由父给件显式去除,Static不能去除。

----ASP.net开发系列内容介绍internalclassYourPropertyTab:PropertyTab
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
internalYourControlTypetarget;
----ASP.net开发系列内容介绍
----ASP.net开发系列内容介绍
publicoverridestringTabName
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
get
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍
return"选项卡的名字";
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍publicoverrideBitmapBitmap
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
get
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍{
----ASP.net开发系列内容介绍
returnnewBitmap(base.Bitmap,newSize(16,16));//这里是使用保存为嵌入资源的和YourPropertyTab类同名的.bmp文件
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍
----ASP.net开发系列内容介绍
publicoverrideboolCanExtend(objecto)
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍
returnoisYourControlType;//什么时候用这个Tab
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
publicoverridePropertyDescriptorCollectionGetProperties(objectcomponent,Attribute[]attrs){
----ASP.net开发系列内容介绍
returnGetProperties(null,component,attrs);
----ASP.net开发系列内容介绍}

----ASP.net开发系列内容介绍
----ASP.net开发系列内容介绍
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
///主要的逻辑.在这里定义如何实现分Tab显示
----ASP.net开发系列内容介绍
----ASP.net开发系列内容介绍publicoverridePropertyDescriptorCollectionGetProperties(ITypeDescriptorContextcontext,objectcomponent,Attribute[]attrs)
----ASP.net开发系列内容介绍----ASP.net开发系列内容介绍
{
----ASP.net开发系列内容介绍YourControlTypeuc
=componentasYourControlType;