一切福田,不離方寸,從心而覓,感無不通。

reset.css

  html, body, div, span, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em,  img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,b,  i, dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent;}body { line-height: 1;}ol, ul { list-style: none;}blockquote, q { quotes: none;}blockquote:before, blockquote:after,q:before, q:after { content: ''; content: none;} /* remember to define focus styles! */:focus { outline: 0;} /* remember to highlight inserts somehow! */ins { text-decoration: none;}del { text-decoration: line-through;} /* tables still need 'cellspacing="0"' in the markup */table { border-collapse: collapse; border-spacing: 0;} /* Resetting HTML5! */section, article, aside, header, footer, nav, dialog, figure { display:block; }  

龙生   08 Apr 2013
View Details

写自己的CSS框架 Part3:CSS中的Class

  3.1框架中的工具 这个CSS中工具有点像C#中的static class,把一些常用的方法放到类里面达到可复用的效果.在CSS中.有很多CSS class是在我们在项目设计中一遍又一遍的要用到的.因此这些tool是CSS框架中必不可少的一部分。   3.2工具类的组成和组织方法 一般现有框架会把这个.class的定义放到各个不同的文件中比如,from.css(用于格式化表单),typography.css(用于格式化布局),但是这个工具类却是我们自己写框架的精髓所在,因为这是我们框架中可以扩展的部分,所以我更喜欢把css class单独命名为tool.css来存放这些工具类.(因为这样在网站改版时就要愉快很多) 也许废话太多了.下面简单给出几行代码,让大家对所谓的Tool.css有初步了解。   Code 1/* 用于格式化Form的CSS Tool 2 3————————————————————-- */ 4 5 6 7.error, 8 9.notice, 1011.success    { padding: .8em; margin-bottom: 1em; border: 2px solid #ddd;}12131415.error      { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4;}1617.notice     { background: #FFF6BF; color: #514721; border-color: #FFD324;}1819.success    { background: #E6EFC2; color: #264409; border-color: #C6D880;}202122 这是用于表单的一些CSS类.有了这些.我可以让项目中每一个使用表单的地方风格实现统一. 而使用JS的地方可以更加简洁.下面一小部分代码是使用了JQUERY从服务器获得AJAX响应后的代码片段 Success:function(data){     $(“<span>”+data+”</span>”).addClass(“success”).appendTo(“#result”); } 恩.是不是简单多了? PS:看客:你不是号称CSS框架吗.这样写不就是把css放一起吗?吹的那么玄乎. 别急嘛.下面讲到CSS之间的组织方式 在我被CSS蹂躏的经历里,其实有很多CSS布局,以及CSS选择符方面问题,大部分是因为CSS选择符之间优先级的关系,这些问题因为简单,所以折磨的各位Developer痛不欲生.但是这些问题就像枪一样,好好利用可以保护你,如果利用不当会让你遭殃。 下面说说我总结的CSS的OCP原则(开放封闭原则),这个规则是设计模式里的,但我发现在CSS中同样适用.   当你针对项目的CSS基本框架写好后,可以添加你所需要的元素,但如非必要,不要去修改它,而是在需要修改的地方重载。 重载: 以上面的例子为例.如果我们在一个特定页面里,想让error颜色变得更加刺眼比如让error的color变成red,只需在你需要修改的特定页面头部的<style>标签中设置   1.error{23Color:red;45}6 因为内页 style比外联style有更高的权值(如果你对CSS的优先级问题不太了解,参考这个文章http://www.xker.com/page/e2009/0622/72573.html),所以error显示的字就会变成红的,但同时又会保留了background和border-color的属性.因此我可以更优雅的覆盖原有CSS,达到重载的目的. 扩展: 当我们需要一组新的css类时,只需要在tool.css相应部分增加即可,比如我们需要表单增加一个介于notice和error之间警告程度的alert用于显示那些有点警告意味的信息.我们只需要加入 1.alert23{45/*——代码写在这—-*/67}8 这样做的优势: 1.代码更加优雅,维护更加方便 2.容易变换网站风格,举个例子,如果你原来的颜色风格偏深,那么你想换一套浅颜色的风格,只需要改变你所需要改变的部分,把你需要改变的部分重新写一个CSS来覆盖原来的CSS,示例代码如下:   <link href="css/tool.css" rel="stylesheet" type="text/css"/><link href="css/toolBlue.css" rel="stylesheet" type="text/css"/> 这样看起来tool.css是不是很“面向对象”,很像基类,而toolBlue像子类,继承那些padding和magin之类的布局属性,而重载color等风格属性,oh yes,life seems like more easier than ever bofore:–)   3.3写在最后 下面我拿出一个简单的tool.css展示出来,让大家有个更直观的了解。   Code/*用于格式化Form的CSS Tool ————————————————————-- */ .error, .notice,  .success    { padding: .8em; margin-bottom: 1em; border: 2px solid #ddd;} .error      { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4;} .notice     { background: #FFF6BF; color: #514721; border-color: #FFD324;} .success    { background: #E6EFC2; color: #264409; border-color: #C6D880;} .error a    { color: #8a1f11;} .notice a   { color: #514721;} .success a { color: #264409;} /*用于布局方面的css tool ————————————————————-- */ .clear {      clear: both;      display: block;      overflow: hidden;      visibility: hidden;      width: 0;      height: 0; } .clearfix {      display: inline-block; } //用于显示方框,实际应用中我喜欢加边框 .box {  padding: 1.5em;  margin-bottom: 1.5em;  background: #E5ECF9; } /*根据项目自定义的css tool ————————————————————-- */ //以下几个是用于和js交互时使用 .hide { display: none;} .highlight   { background:#ff0;} .added      { background:#060; color: #fff;} .removed    { background:#900; color: #fff;} //下面是关于字体的 .small {  font-size: .8em;;  } .large {  font-size: 1.2em; } //还有其他你自定义的class….etc…     恩.基本经常要用到的就是这些,但tool.css的重点在于随着你项目的进展,这个tool.css也会越来越胖. J […]

龙生   08 Apr 2013
View Details

写自己的CSS框架 Part2:跨越浏览器的reset

  2.1浏览器的差异在何处   我想写CSS的人大多遇见过在IE里写的页面美轮美奂,而用FF打开却是分崩离析,反之亦然.这种痛苦是因为IE和FF对一些默认样式的解析并不相同所导致. 网上有很多为何不一样的例子,下面链接是一个比较全的不同之处,大家可以进去看看。 http://hi.baidu.com/css%D6%AE%C3%C0/blog/item/f44628e6a506c229b83820ef.html   2.2如何实现跨浏览器 2.2.1实现原理 既然问题出在FF和IE对各种不同HTML元素的解析上所有偏差.更不用说一些其他小市场份额的浏览器上.我们只需要针对性的把页面里大多数HTML元素重置即可.这样在各种浏览器里面显示的效果会是相同的. 2.2.2实现方式 重置我们选择的名称和大多数框架一样,reset.css,用我们Develper的思想理解——--框架中所有元素的基类,就像.net里的Object对象一样。 下面我们来说说reset.css的构成. 1.首先定义最基本的body,因为所有其他元素都由此继承.我喜欢的框架遵循“尽量保持小”的原则,所以我只简单清除padding和margin,以及设置字体(设置成具体数值,因为在后面用’em’做单位的时候都要以这里做比较,页面风格需要整体变化时,重载这里.) 2.将大量浏览器预定义的块状元素清除magin和padding(块装元素即在未定义样式的情况下浏览器render出来的方式为display:block;的元素) 3.让列表前面的符号消失,图片边框消失,p的上下边距为一行字. 我喜欢reset.css尽量保持简洁.只要实现了基本的重置即可.      PS:不过也不能过于简洁.记得曾经的框架喜欢对”*”这个CSS选择符重置.可是这个杀伤力太大,往往是杀敌1000自伤800,遇到input之类的表单元素时还得重置回来.最后据传说这样还有性能问题-.-!!不过难以考证… 下面是满足上面条件最基本的reset.css     Code1.body { 2.    padding: 0; 3.    margin: 0; 4.    font: 13px Arial, sans-serif; 5.    } 6.    body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset ,p,blockquote { 7.    padding: 0; 8.     margin: 0; 9.    font-weight: normal; 10. font-style: normal; 11. line-height: 1em; 12. font-size: 100%; 13. } 14. table { 15. font-size: inherit; 16. font: 100%; 17. } 18. ul { 19. list-style: none; 20. } 21. img { 22. border: 0; 23. } 24. p { 25. margin: 1em 0;}   这个reset.css是目前我个人最喜欢,因为reset.css就像.net中的Framework中的Object类一样,应该尽量保持精简,这个精简了很多.只留下了必要的重置. 在这里值得一说的是:在body里将font的大小和字体设置了具体的值,在其他元素里通过继承的方式来重写这样的方式是我最喜欢的,这样可以很容易的保持页面整体风格的统一 2.3一些注意事项 Reset.css一经写好,除了BUG之外.永远不要去修改它.而是在其它页面中重载它(不知道用OO的方式理解CSS是否正确,即利用CSS的优先级特性覆盖.这个在下一章说到.) http://www.cnblogs.com/CareySon/archive/2009/07/07/1518543.html

龙生   08 Apr 2013
View Details

写自己的CSS框架 Part1:为什么需要CSS框架

  1.1为什么需要CSS框架  其实这个问题如果要罗列出来网上有一大堆.但是对我们这些”I’m a web developer more than web designer”的人来说,有时候看似简单的CSS却成了网站设计最让人心力憔悴的部分.所以我还是要罗列一下使用CSS框架的好处. PS:一位看客:我们有前台,还有美工,为什么我还要整个什么CSS框架?答曰:我等在小公司没有如此优厚的条件,一个人从前台JS,XHTML,CSS到后台C#,再到Database全是我们2-3个人..所以,请有条件不用兼web designer的看客不要拍砖-.-!! 1.1.1解放生产力 我们对在VS里建立一个新项目太熟悉了.但却往往不知道该怎么处理CSS问题,随着项目的进行,页面设计总是有所变化.这些变化往往会让没有使用CSS框架的你擦掉几乎所有的CSS然后重写.好吧.你赌气想,我开始不写CSS了,等项目后期再写..可是后来你发现外观丑已经让你心情低落了.而和JS交互的那部分CSS你还不得不写.这足以让你抓狂了.而CSS框架可以把你从这种痛苦里解救出来. 1.1.2代码结构清晰,避免混乱和冲突 通过对CSS的清晰有条理的定义.会让我们节省更多的时间专注在设计页面上, 而不是费劲的去查找自己所需要更改的样式. 1.1.3更好的团队合作 我深受混乱的CSS带来的痛苦.我和一位同事曾经一起通过VSS编写样式, 有一个定位的CSS无论我怎样修改,那个元素纹丝不动.找了半天原来.才发现我同事在更高级别的CSS上面进行了定义. 我当然无论怎样定义都不行了,使用CSS框架可以避免此类尴尬.. 1.1.4跨浏览器 这个当然是使用CSS框架的一个亮点,因为IE和FF以及其他市场小份额的浏览器对不同样式预定义的解析方式有所差异.导致用IE测试做出的页面在FF里完全崩溃.进而导致你也崩溃-.-!!反之在FF里测的页面在IE里又崩溃了.导致你也跟着再次崩溃-.-!! 1.1.5依托CSS框架有一个更好的工作流程 我想这个不难理解.大多Developer对CSS头痛的原因就是因为感觉无从下手,而CSS框架让你有路可寻. 1.1.6节省下载流量 CSS框架会让你大幅减少重复定义的次数,进而减少需要下载CSS文件的 流量. 1.1.7网站变换风格更加容易 在项目对整体颜色或者效果改版时.之需要略微改动下项目的CSS框架文件, 或是写个新的CSS文件对框架进行部分覆盖.即可达到效果. 1.2 为什么网上已有那么多CSS框架,我还要自己写 其实我也是从使用网上成型的CSS框架开始,不可否认,他们的CSS框架写的非常优秀,有很多地方可以借鉴.我曾经以为使用熟练一个框架已经足够,可是工作中使用别人的框架产生了一系列问题.下面我一一分解. 1.2.1 必须深入了解框架的每一行代码 因为如果你不仔细学习你所使用的框架的代码,你会发现工作中总会有一些“灵异现象”,你明明这么定义,页面却是那样. 还有就是仔细阅读框架的代码的学习成本足以让你自己写一个自己专用的框架。 1.2.2 别人的框架不一定适合你 因为别人的框架并不会完全适合你的项目,而网上的CSS框架往往过于臃肿,自己写框架当然会对项目更有针对性。 1.2.3 自己写CSS框架会让自己的CSS水平有质的提升并更加针对自己的项目 这也算是题外话了J不过自己写CSS框架以及学习CSS框架的写法是一种CSS学习.会让自己的CSS水平站在一个新的高度,这也是本系列文章所希望的. http://www.cnblogs.com/CareySon/archive/2009/07/06/1517912.html

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(十二)—-数据绑定

  数据绑定和服务器控件模板互为补充,数据绑定用于从数据库中提取数据,而上一章说的服务器控件模板是将这些数据以一定的格式显示在网页中,对于大多数网站来说,根据内容生成特定的html非常常见,而对于开发人员来说,从数据库中提取出数据再以一定的格式显示到网页上是经常需要完成的工作,而这些大多都利用GridView,Repeater等控件的数据绑定功能。 一个典型的过程如下图: 控件的数据绑定 数据绑定有几种不同的形式,对于简单的数据绑定来说,仅仅是将一个数据表达式求值并将该值赋给某个属性,比如下面代码: <asp:Labelid="MyLabel"runat="server"Text="<%= MyDataBoundMethod() %>/> 这段代码是将一个函数的返回值最为label的Text属性. 而对于另外一些较为复杂的数据绑定控件来说,数据绑定意味着一大堆的数据以迭代的形式来帮定到一大堆的控件上来生成html.比如GridView会以Table的形式展现数据。而每一行<tr>内部用于格式的HTML会相同,而内容则有差异.   数据绑定控件的基类 和前面说的一样,在控件开发时选择合适的类作为基类是很重要的,而支持数据绑定的基类主要是从下面几个基类中去进行选择: System.Web.UI.WebControls.DataBoundControl:这个类是所有数据绑定类的基类。 System.Web.UI.WebControls.CompositeDataBoundControl:这个类继承于DataBoundControl基类,用于复合服务器绑定控件 System.Web.UI.WebControls.HierarchicalDataBoundControl:基于树的分层控件的基类   在asp.net中,默认的数据绑定控件分布如下图:   而用更清晰一些的视图来表示几个数据绑定基类之间的关系是:   上面几个基类中,重写了DataBind方法(最开始是定义在Control当中),使DataBind调用PerformSelect,该方法能够检索有效的数据集合以使绑定发生。该方法是受保护的,因为它包含实现细节;它是抽象的,因为它的行为只能由派生类实现。 如果不是基于IDataSource(比如那些SqlDataSource,也就是通过DataSourceID属性来定义的)来获取数据,PerformSelect方法内部会执行GetData方法来获取数据,而在调用GetData方法之前,会触发OnDataBinding事件。而之后则会触发DataBound事件 下面是MSDN中PerformSelect的源码: protected override void PerformSelect() {               // Call OnDataBinding here if bound to a data source using the // DataSource property (instead of a DataSourceID), because the // databinding statement is evaluated before the call to GetData.        if (! IsBoundUsingDataSourceID) {         OnDataBinding(EventArgs.Empty);     }               // The GetData method retrieves the DataSourceView object from  // the IDataSource associated with the data-bound control.                 GetData().Select(CreateDataSourceSelectArguments(),          OnDataSourceViewSelectCallback);   // The PerformDataBinding method has completed.     RequiresDataBinding = false;     MarkAsDataBound();   // Raise the DataBound event.     OnDataBound(EventArgs.Empty); } 从代码中可以看出GetData利用OnDataSourceViewSelectCallback回调来调用PerformDatabinding方法,而PerformDataBinding方法又利用CreateControlHierarchy方法来构建子控件。在调用过CreateControlHierarchy方法后,这个方法会将空间内部的ChildControlIsCreated属性设置成True,从而数据绑定控件不会继续调用CreateChildControl来防止子控件被重复创建,如下是OnDataSourceViewSelectCallback和PerFormDataBinding的源码: privatevoid OnDataSourceViewSelectCallback(IEnumerable retrievedData)         { // Call OnDataBinding only if it has not already been // called in the PerformSelect method. if (IsBoundUsingDataSourceID)             {                 OnDataBinding(EventArgs.Empty);             } // The PerformDataBinding method binds the data in the // retrievedData collection to elements of the data-bound control.             PerformDataBinding(retrievedData);         }} protectedoverridevoid PerformDataBinding(IEnumerable data)         { base.PerformDataBinding(data);             Controls.Clear();             ClearChildViewState();             TrackViewState(); if (IsBoundUsingDataSourceID)                 CreateControlHierarchy(true, true, data); else                 CreateControlHierarchy(true, false, data);             ChildControlsCreated = true;         } CreateChildControls方法一般用于创建组合控件。在此方法中可以定义自己需要的控件,进行实例化和赋值等,并将其添加到当前Controls集合中。数据绑定的生成方式和用此方法的方式的不同之处可用下图表示:   1-5是数据绑定方式,而6-9是利用CreateChildControls方法来进行创建 http://www.cnblogs.com/CareySon/archive/2009/10/29/1591807.html

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(十一)—-服务器控件模板

  在Asp.net 2.0以后的版本,Asp.net提供了服务器控件模板(Template)和数据绑定(Data Bind)来简化开发工作,模板是是用于定制化服务器控件或者HTML如何在页面呈现,而模板和数据绑定往往结合起来在一起实现更高级的功能,比如最经典的GridView.例如,在 GridView服务器控件中可以使用 HTML 元素和控件的组合来创建列表中每行的布局。同样,GridView服务器控件对网格中的每行都具有一个默认的外观。但是,您可以通过为单个行、间隔行、所选行等行定义不同的模板来自定义网格的外观。   定制控件内容 模板用于让开发人员自定义HTML或者服务器控件作为主要控件输出流的一部分。提供了模板的服务器控件其实是给予插入自定义内容提供了容器。 服务器控件模板的强大之处在于它通过让开发人员可以定制输出特定的html来给予了开发人员极高的灵活性.如下图: 使用服务器控件模板 使用服务器控件模板的一大好处是我们可以专注开发空间,而把外观等html和css设置内容让其他人来完成。 在GridView控件里,我们可以通过在ItemTemplate里设置任何我们想设置的内容,在DropDownList控件中我们可以插入ListItem子控件,但在里面插入比如TextBox控件则不行。这个原因就要说到下面一个标签(Attribute)   ParseChildren Attribute 服务器控件必须通过在类声明时添加ParseChildren标签来告诉asp.net页面分析器这个控件需要支持模板。ParseChildren的功能是让服务器控件所含有的子控件作为它的一个属性存在。 对于继承System.Web.UI.WebControls.WebControl基类的控件,这个标签已经通过继承而存在不需要再声明  ParseChildren标签还暴露了ChildrenAsProperties属性,在使用 可以:ParseChildrenAttribute(ChildrenAsProperties = true) 也可以用简便写法:ParseChildren(true) ChildrenAsProperty属性的作用是让控件的属性和直接在控件内部的html代码,或者说是XML代码(“<”和”>”)进行匹配.如下图: 而不使用ChildrenAsProperties属性的则会是如下图:     下面通过一个Demo来看 Demo 服务器导航菜单 先看Demo的效果 先声明两个用于存放子控件的容器,代码如下: publicclassBasicTemplateContainer : WebControl, INamingContainer     { public BasicTemplateContainer(): base(HtmlTextWriterTag.Div)         { this.BorderWidth = 1; this.BorderStyle = BorderStyle.Solid;         }     } publicclassSeperatorTemplateContainer : WebControl, INamingContainer     { public SeperatorTemplateContainer(): base(HtmlTextWriterTag.Span)         {         }  } 第一个用于存放HeaderTemplate和footerTemplate,而第二个用于存放分隔符 再声明一个存放菜单超链接的容器,代码如下:     [TypeConverter(typeof(ExpandableObjectConverter))] publicclassMenuItemData     { public MenuItemData()         {         }         [NotifyParentProperty(true)] publicstring Title { get; set; }         [NotifyParentProperty(true)] publicstring Url { get; set; }         [NotifyParentProperty(true)] publicstring ImageUrl { get; set; }         [NotifyParentProperty(true)] publicstring Target { get; set; }     } 最后声明一个继承于CompositeControl基类的控件,声明代码如下: publicclassTemplateMenu : CompositeControl 最终完全代码如下:     TemplateMenu完全代码  1using System;  2using System.Web;  3using System.Web.UI;  4using System.Web.UI.WebControls;  5using System.Collections;  6using System.ComponentModel;  7using System.Web.UI.WebControls;  8namespace bindcontrol  9{ 10    [ToolboxData("<{0}:templatemenu runat=server></{0}:templatemenu>")] 11publicclass TemplateMenu : CompositeControl 12    { 13private ArrayList menuData; 14public TemplateMenu(): base() 15        { 16        menuData =new ArrayList(){ 17 18new MenuItemData{Title="博客园", Url="http://www.cnblogs.com"}, 19new MenuItemData{Title="Microsoft", Url="http://www.microsoft.com"}, 20new MenuItemData{Title="ASP.Net", Url="http://asp.net"}}; 21        } 22private ITemplate headerTemplate; 23        [Browsable(false), Description("The header template"), 24        PersistenceMode(PersistenceMode.InnerProperty), 25        TemplateContainer(typeof(BasicTemplateContainer))] 26public ITemplate HeaderTemplate 27        { 28get 29            { 30return headerTemplate; 31            } 32set 33            { 34                headerTemplate = value; 35            } 36        } 37private ITemplate footerTemplate; 38        [Browsable(false), Description("The footer template"), 39        PersistenceMode(PersistenceMode.InnerProperty), 40        TemplateContainer(typeof(BasicTemplateContainer))] 41public ITemplate FooterTemplate 42        { 43get 44            { 45return footerTemplate; 46            } 47set 48            { 49                footerTemplate = value; 50            } 51        } 52private ITemplate separatorTemplate; 53        [Browsable(false), Description("The separator template"), 54        PersistenceMode(PersistenceMode.InnerProperty), 55        TemplateContainer(typeof(SeperatorTemplateContainer))] 56public ITemplate SeparatorTemplate 57        { 58get 59            { 60return separatorTemplate; 61            } 62set 63            { 64                separatorTemplate = value; 65            } 66        } 67privatevoid CreateControlHierarchy() 68        { 69if (HeaderTemplate !=null) 70            { 71                BasicTemplateContainer header =new BasicTemplateContainer(); 72                HeaderTemplate.InstantiateIn(header); 73                Controls.Add(header); 74            } 75int count = menuData.Count; 76for (int index =0; index < count; index++) 77            { 78                MenuItemData itemdata = (MenuItemData)menuData[index]; 79                HyperLink link =new HyperLink() 80                { 81                    Text = itemdata.Title, 82                    NavigateUrl = itemdata.Url, 83                    ImageUrl = itemdata.ImageUrl, 84                    Target = itemdata.Target 85                }; 86                Controls.Add(link); 87if (index != count –1) 88                { 89if (SeparatorTemplate !=null) 90                    { 91                        SeperatorTemplateContainer separator =new SeperatorTemplateContainer(); 92                        SeparatorTemplate.InstantiateIn(separator); 93                        Controls.Add(separator); 94                    } 95else 96                    { 97                        Controls.Add(new LiteralControl(" | ")); 98                    } 99                }100            }101if (FooterTemplate !=null)102            {103                BasicTemplateContainer footer =new BasicTemplateContainer();104                FooterTemplate.InstantiateIn(footer);105                Controls.Add(footer);106            }107        }108overrideprotectedvoid CreateChildControls()109        {110            Controls.Clear();111            CreateControlHierarchy();112        }113publicoverride ControlCollection Controls114        {115get116            {117                EnsureChildControls();118returnbase.Controls;119            }120        }121    }122123publicclass BasicTemplateContainer : WebControl, INamingContainer124    {125public BasicTemplateContainer(): base(HtmlTextWriterTag.Div)126        {127this.BorderWidth =1;128this.BorderStyle = BorderStyle.Solid;129        }130    }131publicclass SeperatorTemplateContainer : WebControl, INamingContainer132    {133public SeperatorTemplateContainer(): base(HtmlTextWriterTag.Span)134        {135        }136    }137    [TypeConverter(typeof(ExpandableObjectConverter))]138publicclass MenuItemData139    {140public MenuItemData()141        {142        }143        [NotifyParentProperty(true)]144publicstring Title { get; set; }145        [NotifyParentProperty(true)]146publicstring Url { get; set; }147        [NotifyParentProperty(true)]148publicstring ImageUrl { get; set; }149        [NotifyParentProperty(true)]150publicstring Target { get; set; }151    }152} 前台调用代码如下: 首先注册控件:<%@Register Namespace="bindcontrol"TagPrefix="dd"%> 然后是前台代码: <dd:TemplateMenurunat="server"> <HeaderTemplate>template header</HeaderTemplate> <SeparatorTemplate>%</SeparatorTemplate> <FooterTemplate>template footer</FooterTemplate> </dd:TemplateMenu> 注意,作为模板的类型必须声明成ITemplate类型,而这个ITemplate的具体类型则通过TemplateContainer标签进行注入.我们通过声明CreateControlHierarchy()函数来进行控制控件的具体输出,最后通过覆盖父类的CreateChildControls()方法来调用我们写好的CreateControlHierarchy方法达到控制输出的目的。   最后,你可能有疑问,那个神奇的ChildrenAsProperties属性跑哪去了?如果没有这个属性,那上面<headerTemplate>之类的标签又是如何匹配的呢?还记得吗,继承与WebControl基类的控件继承了这个标签,所以不用显示声明,所以ChildrenAsProperties属性come for free:-) http://www.cnblogs.com/CareySon/archive/2009/10/19/1586146.html

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(十)—-服务器控件生命周期

  在每一次http的Request和Response周期asp.net web form都会执行一系列被称为控件生命周期的预定义过程     在第一次通过HTTP Get方法获取到页面后,每一次向服务端进行HTTP POST回传都会分为以下几个步骤: 1.初始化控件树 2.将回传的ViewState进行解析 3.根据前几次的回传解析来为控件树中的每一个控件设置状态 4.处理回传数据 5.处理Page_Load事件 6.通过PostBack通知控件的数据变化,并在必要的情况下更新控件状态 7.执行基于控件状态改变的服务端事件(比如button的点击) 8.将控件状态持久化为ViewState 9.按照次序Render控件树中的每一个控件 10. Dispose整个页面和控件树 由上面的列表可以看出整个的用户Request和服务器Response的周期,首先是将状态解析并根据控件的状态来处理状态的改变,最后处理完后将这些Render回客户端,并将新的状态以ViewState的形式保存在客户端的hidden form中。     页面生命周期对应事件 在页面生命周期中,上面所说的每一个步骤都有一个对应的事件。这也就意味着你可以通过Override事件的执行方法来在页面周期中插入你自己的实现 服务端事件 页面生命周期 描述 Init Initialization 初始化控件树 LoadViewState Unpack ViewState 从ViewState里提取出状态信息 LoadControlState Unpack control state 从控件状态中提取出状态信息 LoadPostData Handle form postback 从PostBack信息中更新控件状态信息 Load Page_Load event 执行Page_Load内的事件 TrackViewState Track ViewState   RaisePostDataChangedEvent Initialization for server-side events 通知控件回传的状态将改变其值 RaisePostBackEvent Execute server-side events 对于指定的控件,如果状态信息改变,则引发该事件 PreRender Render process 让每个空间接收最新的状态信息 SaveViewState Save ViewState 保存ViewState SaveControlState Save control state   Render Render process Render标准HTML,Render的HTML带有控件的状态信息 Dispose Dispose of control tree 释放资源   服务器生命周期和HTTP GET以及HTTP POST 在System.Web.UI.Control基类定义了OnInit, OnLoad, OnPreRender, OnUnload,这四个事件可以被重写。而对于Dispose事件虽然Control也有定义,但并没有相应的OnDispose方法来引发事件,如果需要Dispose事件,需要实现IDispose接口。 在通常情况下,第一次访问aspx页面时通过HTTP GET方法,而第二次以后都会通过HTTP POST方法,而HTTP POST方式进行访问服务器时,所需要经历的过程要比GET方式多,因为它包含了数据回传处理,下面是示意图: 下面通过一个小Demo来查看控件的生命周期: Demo Post回传生命周期 首先先写一个控件,对每个控件的上述事件进行覆盖,最后通过在页面Trace来查看 首先是控件的代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI;   namespace Life {     [ToolboxData("<{0}:lifecycle runat=server></{0}:lifecycle>")] publicclassLifecycle : Control, IPostBackEventHandler, IPostBackDataHandler     { protectedoverridevoid OnInit(System.EventArgs e)         {             Trace("Lifecycle: Init Event."); base.OnInit(e);  } protectedoverridevoid TrackViewState()         {             Trace("Lifecycle: Track ViewState."); […]

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(九)—-服务器控件事件

  EventCollection 如果在单个控件中有多个事件,那么使用System.ComponentModel.EventHandlerList对事件进行保存将会在内存占用上有不错的提高。EventHandlerList对一个类内发布多个事件提供了一个列表容器。下面是多个事件和使用EventHandlerList的对比示意: 第一步是实例化一个EventHandlerList的实例: protected EventHandlerList eventList = new EventHandlerList(); 第二步是声明一个容器用于保存事件的key privatestaticreadonlyobject ClickEvent = newobject(); 最后一步是像往常一样声明一个事件,但有所不同的是就像属性的get和set程序块一样,对于事件C#提供了add和remove关键字: publiceventEventHandler Click         { add             {                 Events.AddHandler(ClickEvent, value);             } remove             {                 Events.RemoveHandler(ClickEvent, value);             }       } 而在这时的事件调用方法就会像下面代码: protectedvirtualvoid OnClick(EventArgs e)         { EventHandler clickEventDelegate = (EventHandler)Events[ClickEvent]; if (clickEventDelegate != null) {                 clickEventDelegate(this, e);             }      } 上面代码首先从事件列表中通过索引器以第一步中保存事件的key为参数提取出事件并检查客户端是否注册到此事件,如果是,则激发事件。   Command事件和事件冒泡 Command事件是System.Web.UI.WebControls命名空间里的强大模式。这个最好的例子是GridView 在GridView的Row里嵌套的button点击会触发Command事件,后台可以根据CommandArgument的不同来决定是执行edit操作还是delete操作等。而事件冒泡有些像javascript里的事件冒泡,但有所不同的是这里的事件冒泡到能够处理这个事件的地方停止,比如上图中command事件会冒泡到DataGrid里的ItemCommand里停止,因为ItemCommand事件可以对command事件进行处理. 在定义Command事件时会和前面大同小异,不同之处在于首先需要一个继承与System.EventArgs的CommandEventArgs类来进行参数传递,代码如下 publicclassCommandEventArgs : EventArgs { public CommandEventArgs(string _commandName,string _commandArgument) {     CommandName=_commandName;     CommandArgument=_commandArgument; }  privatestring commandname; privatestring commandArgument; publicvirtualstring CommandName         { get             { return commandname;             } set             {                 commandname = value;             }         } publicvirtualstring CommandArgument         { get             { return commandArgument;             } set             {                 commandArgument = value;             }         } } 然后在需要定义的控件里定义这两个属性,代码如下: publicvirtualstring CommandName          { get             { object name = ViewState["CommandName"]; if (name == null) returnstring.Empty; else return (string)name;             } set             {                 ViewState["CommandName"] = value;             }         } publicvirtualstring CommandArgument         { get             { object arg = ViewState["CommandArgument"]; if (arg == null) […]

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(八)—-服务器控件事件

  事件和委托之间的暧昧关系往往是大多Web Developer在学习.net中的一个里程碑,当明白事件和委托的关系后,.net水平往往就上了一个新的台阶.下面说到服务器控件的事件模型. 在任何一个服务器编程开发框架中,事件都是解耦功能和具体实现的一剂良方,Asp.net当然也不例外。比如说吧,页面上的button的click事件表示它的功能,而具体的实现将会被分离交给Developer来进行具体实现。 传统的编程模型和基于事件的编程模型可以用下图进行简约概括: 我们可以看出事件极大的简化了编程工作,客户端程序只需要注册到事件并且和事件的签名保持一致(即参数个数和类型相同)即可。在事件发生后,客户端程序会被通知并执行相应实现(.net framework的事件正是观察者模式的最好例子:-))   Asp.net通过ViewState和Http Post协议巧妙的实现了让开发人员感觉貌似控件能像WinForm程序中那样记住自己的状态。这使Asp.net可以在不使用客户端javascript的情况下,而实现数据回传。       上面的图例展示出TextBox通过暴露相应的事件来通知被注册的函数.还记得前面所说的IPostDataHandler接口嘛,大多数服务器控件的事件都是通过ViewState来将数据以Http Post协议传回服务器,服务器根据回传数据的不同来引发相应事件。因此我们可以看出Button控件生成的<input type=”submit” />是有往服务器提交的功能的,而其他控件比如DropDownList或者是Checkbox是没有像服务器提交的功能。因此引发服务器事件便无从谈起。Asp.net通过在客户端设置javascript事件来引发向服务器的Http Post回传。而这一切仅仅需要将AutoPostBack属性设置为true.     .net FrameWork 事件模型 .net framework提供了基于委托的使不同类之间进行异步交互的机制。下面先简单说一下事件的核心——-委托   Delegate 委托在一定程度上有点像接口,是在发布者和订阅者之间的一个协议。接口是制订类的数据成员以及成员函数的签名。而委托,是制订单个函数的签名. 创建一个委托的实例是通过创建一个和委托相匹配的函数。 MSDN里把委托比喻成类型安全的函数指针。但是委托不仅限于此,因为.net framework大大的扩展了这个“类型安全的指针”,在CLR via C#这本书里说委托的实质上是一个类。因此委托可以按照次序依次调用多个匹配的方法,无论是静态方法还是实例方法。 委托有两个部分,委托的声明和委托实例的声明。 委托的声明代码会像: publicdelegatevoidfoo(string A); 而委托实例的声明会像 foo f=new foo(MethodName)   下面通过一个简单的Demo说明一下:   Demo 委托 先写一个简单的类: publicclassDelegateDemo     { publicdelegatevoidDeleDemo(string a); publicstaticvoid FunctionA(string a)         { HttpContext.Current.Response.Write("静态方法,传入的参数是:" + a + "<br />");         } publicvoid FunctionB(string a)         { HttpContext.Current.Response.Write("实例方法,传入的参数是:" + a + "<br />");         } } 下面是客户端代码: DelegateDemo dd = newDelegateDemo(); DelegateDemo.DeleDemo d = newDelegateDemo.DeleDemo(dd.FunctionB);         d += DelegateDemo.FunctionA;     d("参数");   最后的输出结果为: 实例方法,传入的参数是:参数静态方法,传入的参数是:参数   通过上面小Demo可以发现委托不仅仅是“类型安全的指针”,并且委托是按照次序调用实例方法和静态方法.   事件 C#里有专门用于声明事件的event关键字,一个典型的事件生命会像: publiceventEventHandler click;   事件关键字后面是委托,再后面是事件名称,命名事件的名称最好是动词,表名某些事情发生了。比如click,Init,Load,TextChanged这样。由此可以看出事件其实就是特殊的委托。因为所有的事件都是继承于System.EventHandler.   EventHandler 委托 所有asp.net内置控件事件处理函数的签名都和EventHandler或者继承于它的子类保持一致。它的原型是: [SerializableAttribute] [ComVisibleAttribute(true)] publicdelegatevoidEventHandler( Object sender, EventArgs e )   第一个参数表示引发事件的对象,第二个参数表示引发事件后所要传给处理程序的参数。   在一般情况下,开发人员最好是按照这种签名格式来声明函数事件的委托.   在控件内部声明事件后,你必须在需要的情况下引发事件,直接引发事件是非常不好的做法。而在asp.net预定义的控件中都使用了如下方法: 声明一个virtual protected void的方法,命名方式为On+事件名称.下面是一个例子: protectedvirtualvoid OnClick(EventArgs e)         { if (Click != null)                 Click(this, e);        } 这个方法首先做的是先检查客户端方法是否注册,如果有客户端方法进行了注册,则引发事件。 http://www.cnblogs.com/CareySon/archive/2009/10/12/1581792.html

龙生   08 Apr 2013
View Details

Asp.net控件开发学习笔记(七)—-WebControl基类

  WebControl基类 在Asp.net控件开发中,WebControl基类给我们提供了对于控件的Style更加灵活的解决方案,因为在System.Web.UI.Control基类中只能手动的输入呈现在客户端的代码,但如果开发的服务器控件对style的要求较高。那Control基类的局限性就显而易见了,而继承WebControl类作为基类将会是很好的选择。      System.web.UI.WebControls.Webcontrol直接继承与Control类。在继承了Control的特性的基础上,WebControl基类不仅在生成客户端html使用了另一种更好的render方式,并且还提供了对于老版本浏览器的兼容。   WebControl的ControlStyle属性    ControlStyle属性其实是System.Web.UI.WebControls.Style的一个实例,这个属性用于读取或者设置常用的CSS类,以下是System.Web.UI.WebControls.Style的属性和CSS属性的对应关系。 Style的属性 CSS标准属性 BackColor background-color BorderColor border-color BorderStyle border-style BorderWidth border-width CssClass CSS的类名 Font Font weight, style, family, and so on ForeColor color Height height width width   而在ControlStyle.Font是一些设置字体的属性,是System.Web.UI.FontInfo对象的实例。和标准CSS属性的对照如下表:   Font 属性 CSS标准属性 Bold font-weight: bold Italic font-style: italic Name font-family Names font-family Overline text-decoration: overline Underline text-decoration: underline Size font-size Strikeout text-decoration: line-through   WebControl基类ControlStyle属性的简化 下面这行代码: webcontrol.ControlStyle.BorderWidth = 1; 和      webcontrol.BorderWidth = 1; 代码是等价的,WebControl基类可以不通过ControlStyle属性而访问ControlStyle内的成员,这样在前台可以直接对控件进行style设置,刚才的后台代码于如下前台代码是等价的: <cc:WebControlid="WebControl"runat="server"borderwidth="1"/>   WebControl的Style属性 因为ControlStyle属性只暴露了一部分可用于操控CSS的属性,而除了上述ControlStyle暴露的基本的CSS属性设置之外,WebControl基类还为我们提供了Style属性用于对CSS进行精确完整的操作,可以用如下图让概念更加清晰:     Style属性是System.Web.UI.CssStyleCollection这个类的实例,style属性大多在.aspx文件中用到,比如: <asp:ButtonID="Button1"runat="server"Text="Button"style="background:blue;"/> 而与上面对Style赋值等价的后台代码则是: Button1.Style["background"] = "blue"; 或者 Button1.Style.Add("background", "blue");   一个新的Render系统 和集成Control并重写Render方法不同,WebControl给我们提供了一个新的系统用于Render控件。下面写一个Label的Demo:   Demo:label控件 代码如下:     [ToolboxData("<{0}:label runat=server></{0}:label>"),DefaultProperty("Text")] publicclassLabel : WebControl     { public Label(): base(HtmlTextWriterTag.Span)         {         } publicvirtualstring Text         { get             { object text = ViewState["Text"]; if (text == null) returnstring.Empty; […]

龙生   08 Apr 2013
View Details
1 2 3