|
主题: 一点一滴学做.NET服务控件
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#12006/6/17 11:16:43
最近学习.NET,除了开发之余,学习一下服务器控件的编程。可能各位都知道,ASP.NET控件分用户控件和服务器控件。用户控件编程相对简单些,一般用得比较多。服务器控件在学习上就相对难一点,但通过一定学习也不难掌握。服务器控件比用户控件要灵活,如果掌握这一点,在开发上会有很大帮助的。
在这里,没有什么必要象教科书一样把知识都列出来,出这一帖,只是想把一些经验和收获写出来。因此,以代码和讨论为主。有什么问题都这里讨论解决。
声明一点,本帖不为教材,各位可随便发,与服务控件有关的都可加到本帖下。
非常大鱼
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#22006/6/17 11:38:07
先发个自己做的文章显示控件,用于显示文章的标题列 主要功能:
显示文章,并可以按一定长度显示 控制显示发布日期的关,并可控制日期显示是否换行 控制显示是否显示NEW图标 设定文章显示样式,标题样式及日期样式等
服务器控件的建立方法与建立普通的类差不多,但服务器控件的继承处Control类或WebControl类,这些要写很长的基础知识就不多说,可以找一些教材或资料。 本例子的控件是继承自WebControl类,因为可以继承一些更多的如EnableViewState、Width、Height、ForeColor等属性。
protected override void Render(System.Web.UI.HtmlTextWriter writer) 说明:该类是继承自WebControl类
在开发服务器控件中,会用到一最常见的方法Render,该方法作用是在网页中呈现html代码,该方法是WebControl类中原有的,因此在开发时,应重写该方法。在服务器控件开发中,还会用到一些其它的Render方法,在以后介绍 protected override void Render(System.Web.UI.HtmlTextWriter writer)
非常大鱼
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#32006/6/17 12:15:58
另外从以上代码中,我们已经接触到了HtmlTextWriter这个类,该类是向WEB页中写出HTML代码。看下面代码:
writer.AddAttribute(HtmlTextWriterAttribute.Target, "_blank"); writer.AddAttribute(HtmlTextWriterAttribute.Href , "http://www.hellosea.com") writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write("东海龙宫"); writer.RenderEndTag();
该代码在网页上呈现: <a href="http://www.hellosea.com" target="_blank">东海龙宫</a>
为什么要使用HtmlTextWriter?
使用该类,使HTML写法很清晰,代码容易管理 可以检查出错,如没有关闭标签,在页面显示时会报出错 执行速度快,比StringBuilder要快很多。如果使用StringBuilder,可能会引起显示速度缓慢
注意: 在使用时,必须先使AddAttribute(添加属性),AddStyleAttribute(添加样式)先写,然后再写RenderBeginTag,不能搞错顺序。
非常大鱼
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#42006/6/17 12:19:27
先帖上控件的全部代码,在下文中解析
// ******************************************************************* // 控件名:ArticleTitleList // 用 途:用于呈现文章标题的显示方法 // 设计者:蓝鲸 // 最后修改日期:2006-6-15 // ******************************************************************* using System; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Data; using Hellosea.WebModule; using Hellosea.WebModule.Article.Data; using Hellosea.WebModule.Article.Business; using Hellosea.Object.Tree;
namespace Hellosea.Control.Article { // ArticleTitleList的呈现方法 [ DefaultProperty("Text"), ToolboxData("<{0}:ArticleTitleList Runat=\"server\"></{0}:ArticleTitleList>") ] public class ArticleTitleList : System.Web.UI.WebControls.WebControl { private int mArticleCategoryID; private int mPageSize = 5; private int mPageNum = 1; private int mMaxTitleLength = -1; private string mHref = "ShowArticle.aspx"; private string mTarget = "_blank";
private string mTitleCss; private string mPubDateCss; private string mPubDateFormateString = "[yyyy-MM-dd]";
private bool mPubDateChangeLine = false; private bool mShowPubDate = false;
private int mNewIconLenth = 2; private bool mShowNewIcon = false; private string mNewIconString = @"<font style=""color:red; font-family:arial; font-size:11px;"">New!</font>";
#region 定义属性 [ Description("该属性为文章的分类号"), Bindable(true), Category("文章属性"), Defaultvalue(0) ] public int ArticleCategoryID { get { return mArticleCategoryID; } set { mArticleCategoryID = value; } }
[ Description("该属性为文章每页显示条数"), Bindable(false), Category("文章属性"), Defaultvalue(5) ] public int PageSize { get { return mPageSize; } set { mPageSize = value; } }
[ Description("该文章显示页号"), Bindable(false), Category("文章属性"), Defaultvalue(1) ] public int PageNum { get { return mPageNum; } set { mPageNum = value; } }
[ Description("文章每记录显示字符最大长度"), Bindable(false), Category("文章属性"), Defaultvalue(-1) ] public int MaxTitleLength { get { return mMaxTitleLength; } set { mMaxTitleLength = value; } }
[ Description("文章链接路径,相对于网站目录"), Bindable(false), Category("文章属性"), Defaultvalue("ShowArticle.aspx") ] public string Href { get { return mHref; } set { mHref = value; } }
[ Description("目标窗口"), Bindable(false), Category("文章属性"), Defaultvalue("_blank") ] public string Target { get { return mTarget; } set { mTarget = value; } }
[ Description("标题样式"), Bindable(false), Category("文章属性"), Defaultvalue("") ] public string TitleCss { get { return mTitleCss; } set { mTitleCss = value; } }
[ Description("日期样式"), Bindable(false), Category("文章属性"), Defaultvalue("") ] public string PubDateCss { get { return mPubDateCss; } set { mPubDateCss = value; } }
[ Description("日期显示格式"), Bindable(false), Category("文章属性"), Defaultvalue("[yyyy-MM-dd]") ] public string PubDateFormateString { get { return mPubDateFormateString; } set { mPubDateFormateString = value; } }
[ Description("显示发布日期是,是否换行"), Bindable(false), Category("文章属性"), Defaultvalue(false) ] public bool PubDateChangeLine { get { return mPubDateChangeLine; } set { mPubDateChangeLine = value; } }
[ Description("是否显示发布日期"), Bindable(false), Category("文章属性"), Defaultvalue(false) ] public bool ShowPubDate { get { return mShowPubDate; } set { mShowPubDate = value; } }
[ Description("New图标相对字符长度"), Bindable(false), Category("文章属性"), Defaultvalue(2) ] public int NewIconLenth { get { return mNewIconLenth; } set { mNewIconLenth = value; } }
[ Description("是否显示New图标"), Bindable(false), Category("文章属性"), Defaultvalue(false) ] public bool ShowNewIcon { get { return mShowNewIcon; } set { mShowNewIcon = value; } }
[ Description("New图标的显示代码"), Bindable(false), Category("文章属性"), Defaultvalue("") ] public string NewIconString { get { return mNewIconString; } set { mNewIconString = value; } } #endregion
public ArticleTitleList() : base(HtmlTextWriterTag.Div) {}
protected override void Render(System.Web.UI.HtmlTextWriter writer) { ShowTitle(writer); base.Render(writer); }
private void ShowTitle(HtmlTextWriter writer) { // 要目录相对路径 WebPageInfo pinfo = WebCode.GetCurrentPathInfo(); string cPath = pinfo.HomeRelativeSite;
// 取得文章的DataSet TreeList categoryTree = ArticleCategoryTool.GetCategoryTree(); String arrIDs = categoryTree.GetAllChildsIDString(mArticleCategoryID, ",", false); if (arrIDs == "") { arrIDs = "(" + mArticleCategoryID.ToString() + ")"; } else { arrIDs = "(" + arrIDs + "," + mArticleCategoryID.ToString() + ")"; } DataSet ds = ArticleTool.GetArticles(arrIDs, false, mPageSize, mPageNum);
writer.RenderBeginTag(HtmlTextWriterTag.Ul); foreach(DataRow row in ds.Tables[0].Rows) { // 标题最大显示字数 int maxLength = mMaxTitleLength; if (mShowPubDate && !mPubDateChangeLine) { int dateLen = WebCode.StringRealLength((Convert.ToDateTime(row["PubDate"])).ToString(mPubDateFormateString)); int titleLen = WebCode.StringRealLength(row["Title"].ToString()); if (dateLen % 2 != 0) { maxLength -= (dateLen + 1) / 2;
if ( WebCode.StringRealLength( WebCode.CutString( row["Title"].ToString(), maxLength) + (Convert.ToDateTime(row["PubDate"])).ToString(mPubDateFormateString ) ) <= (mMaxTitleLength - 1)*2 ) maxLength += 1; } else { maxLength =- dateLen / 2; } }
// 判断是否显示New Icon bool showNewIcon = false; if (mShowNewIcon) { int newDateDiff = WebSiteConfig.GetSettings().Article_NewDateDiff; TimeSpan ts = DateTime.Now.Subtract(Convert.ToDateTime(row["PubDate"])); if (ts.Days < newDateDiff) showNewIcon = true; }
if (showNewIcon) maxLength -= mNewIconLenth;
writer.AddAttribute(HtmlTextWriterAttribute.Class, mTitleCss); writer.RenderBeginTag(HtmlTextWriterTag.Li);
// 显示文章标题 writer.AddAttribute(HtmlTextWriterAttribute.Title, row["Title"].ToString()); writer.AddAttribute(HtmlTextWriterAttribute.Target, Target); writer.AddAttribute(HtmlTextWriterAttribute.Href ,cPath + mHref + "?ArticleID=" + row["ArticleID"].ToString()); writer.RenderBeginTag(HtmlTextWriterTag.A); if (MaxTitleLength < 0) writer.Write(row["Title"].ToString()); else writer.Write(WebCode.CutString(row["Title"].ToString(), maxLength)); writer.RenderEndTag();
// 显示NewIcon if (showNewIcon) writer.Write(mNewIconString);
// 显示日期 if (mShowPubDate) { // 是否日期换行显示 if (mPubDateChangeLine) { writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Class, mPubDateCss); writer.RenderBeginTag(HtmlTextWriterTag.Li); writer.Write( (Convert.ToDateTime(row["PubDate"])).ToString(mPubDateFormateString) ); } else { writer.Write(" "); writer.Write( (Convert.ToDateTime(row["PubDate"])).ToString(mPubDateFormateString) ); } }
writer.RenderEndTag(); } writer.RenderEndTag(); }
} }
非常大鱼
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#52006/6/17 12:42:35
[ DefaultProperty("Text"), ToolboxData("<{0}:ArticleTitleList Runat=\"server\"></{0}:ArticleTitleList>") ]
该代码是用于在控件在aspx页面中呈现方式,如 <cc1:ArticleTitleList RunatRunat="Server" id="ArticleTitleList1"></cc1:ArticleTitleList>
[ Description("该属性为文章的分类号"), Bindable(true), Category("文章属性"), Defaultvalue(0) ]
Description:在属性中显示的提示信息 Bindable:是否可以绑定 Category:在属性栏中的分类,该分类可以自己添加,也可以添加在一些固有分类中,使属性摆放大某分类下 Defaultvalue:默认值 其它还有一些,以后再介绍,现在不要说太多了
protected override void Render(System.Web.UI.HtmlTextWriter writer) { ShowTitle(writer); base.Render(writer); }
Render,前面介绍过的重要方法,用于呈现控件 base.Render(writer);调用基类Render方法,呈现基类的属性 ShowTitle方法,是自定义方法,用一从数据库读取文章,并写html代码
// 要目录相对路径 WebPageInfo pinfo = WebCode.GetCurrentPathInfo(); string cPath = pinfo.HomeRelativeSite; 是自定义类的方法,是自己函数库中的一些函数库,用于取得本页面的一些重要值,本代码取得本页相对根目录的相对路径,表现形式为如“../../”。本类在以前贴子中介绍过,现在暂不讨论
// 取得文章的DataSet TreeList categoryTree = ArticleCategoryTool.GetCategoryTree(); String arrIDs = categoryTree.GetAllChildsIDString(mArticleCategoryID, ",", false); if (arrIDs == "") { arrIDs = "(" + mArticleCategoryID.ToString() + ")"; } else { arrIDs = "(" + arrIDs + "," + mArticleCategoryID.ToString() + ")"; } DataSet ds = ArticleTool.GetArticles(arrIDs, false, mPageSize, mPageNum); // 该方法的树形类介绍在本论坛有过粗略介绍,已经经过改进,该方法的用途是从数据库中取得分类,并整理成树形。 GetAllChildsIDString,是取得某一ID号节点下所有了节点的ID,表现形式为“(1,12,18)”,因某一分类下的文章,可能还是子类的文章,均显示出来。 注:本代码已经经过几次包装,如果看不懂,可以略去,与控件制作方法并不很相关。
DataSet ds = ArticleTool.GetArticles(arrIDs, false, mPageSize, mPageNum); 取得文章内容的类库,为数据层和业务层的类,作用是取得文章内容的DataSet。只了解作用,看时可以略去。
WebCode.CutString 如果文章太长,截取某一段长度,大家可以用自己的函数截取
非常大鱼
|
缺缺
职务:管理员
等级:8
金币:41.0
发贴:9620
注册:2004/1/14 19:14:47
|
#62006/6/22 15:28:51
呵呵 刚看到.写的不错.
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#72006/6/23 10:29:09
allinhands在上个帖子中说 引用: 呵呵 刚看到.写的不错.
哈哈 可能有点烦,来个简单的热热身 using System; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Data; namespace Hellosea.Control.MyTest { public class TestControl : System.Web.UI.WebControls.WebControl { protected override void Render(System.Web.UI.HtmlTextWriter writer) { writer.AddAttribute(HtmlTextWriterAttribute.Target, "_blank"); writer.AddAttribute(HtmlTextWriterAttribute.Href , "http://www.hellosea.com") writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write("东海龙宫"); writer.RenderEndTag(); base.Render(writer); } } }
非常大鱼
|
追梦人
职务:普通成员
等级:1
金币:0.0
发贴:3
注册:2006/3/9 8:25:52
|
#82006/8/7 21:42:09
这个帖子真好。前一阵子刚写完了一个多功能分页控件
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#92006/8/8 8:50:37
aniusky在上个帖子中说 引用: 这个帖子真好。前一阵子刚写完了一个多功能分页控件
能把代码发上来吗,学习一下
非常大鱼
|
xzzhangg
职务:普通成员
等级:1
金币:0.0
发贴:1
注册:2005/6/5 9:11:10
|
#102006/8/10 0:20:40
好象这段时间流行学这个呀,刚好我也在学这个. 楼主这个长长的例子怎么没发自定义命名控件的类代码呀
|
蓝鲸
职务:版主
等级:5
金币:42.1
发贴:2614
注册:2001/12/20 15:57:57
|
#112006/8/10 7:57:18
xzzhangg在上个帖子中说 引用: 好象这段时间流行学这个呀,刚好我也在学这个. 楼主这个长长的例子怎么没发自定义命名控件的类代码呀
因为类都比较长,并且用到几个类,代码太长了。这里只说明一个方法
非常大鱼
|
呵呵
职务:普通成员
等级:1
金币:0.0
发贴:26
注册:2007/7/27 11:06:08
|
#122007/7/27 13:23:21
敲开IT财富的大门,你准备好了吗? 伴随着互联网的发展,社会对IT人才的需求越来越大。除北京、上海外,绝大部分的需求集中在华南、华东地区的大中型城市。而国内目前IT教育主要是高等学校的计算机、电子、电信、信息技术等相关专业的学历教育,每年培养的大学毕业生不到10万人,远远不能满足市场的需求。为了能适应市场对IT人才的需求,作为我们个人来说,应该赶快行动起来,积极加入到IT培训中来,以使自己能适应社会的需要。 一、 选择合适的培训方向 对非计算机科系的人来说,要半路出家进入IT业,既然你选择了软件开发作为自己的奋斗方向,就必须从基础课程学起,注意学习方法,循序渐进,掌握好它们之间的关联性。学习软件开发,如果先把C++学好,再学诸如Java、SQL Server、Oracle、VB、ASP等其他语言时,在程序设计的语法上就十分好理解了;C++学好的同时,如果掌握好计算机操作系统知识,熟悉了Windows的操作与应用,再学习Win32API的程序设计也就有基础了;Win32API的程序设计学好了,几乎所有计算机专业人员都认为十分困难的Visual C++程序设计的学习也就成了一件水到渠成的事情了。掌握好了一两种语言,以后再学习新的语言来就不会太困难,因为不同的语言只是语法上有区别,逻辑结构大部分相似。其他技能也是一样,只要牢固掌握一门技术,就能融会贯通、举一反三。 二、 认真执行培训计划 不论任何技术都有被淘汰的一天,即使我们已经熟悉IT业的许多知识了,但在目前的情况下,还必须不断的培训以便不断地补充和完善自己。IT界的技术服务和支持领域的工作,在当前的经济萧条时期遭受到了一定冲击。而开发和担负重点工程系统体系设计的人,由于其紧跟重点工程的发展而没有受到影响。如果当前你的专业知识仅仅限于一个领域,那么,你就面临着在当前的就业市场变得越来越没有个人价值的危险。 如果你想正式开始学习IT知识时,应该首先扪心自问一下:这一学习计划或IT技术论证能否使自己得到进一步提升,能否在IT行业的价值链中获益?制定的学习计划应该为了进一步提高自己现有的专业才能,而不是为自己填补一些可以充当部门负责人的新才能。一旦确定现在有必要学习的新东西,该如何着手呢?首先需要注意的一点是,不要只是死抱着一两种技术或平台,或只掌握一两种开发语言。现在,用人单位越来越希望招聘到万事通式的人才。所以,你不能满足于只精通Windows或者Linux,或者只会JAVA。要赶快学习其他有关技术,即使不在你的工作范围内。 在现代社会,许多人面临的并不是知识危机,因为很多人都拥有大专以上的学历,知识不再是危机。现代人越来越多的体验到的是本领和技能的危机。他们个人需要培训的愿望很强烈,愿意出钱培训,所以针对本领和技能方面的培训市场会越来越大。另外,现代人生活质量提高了,面对个人兴趣方面的培训市场会多起来,在工作之后,人们根据自己的兴趣爱好来选择一些培训,充实和丰富自己的生活。只有自己时刻保持危机感,敢于让自己跳出舒适的位置,继续拓宽和充实你在IT行业的技能,才能在当今就业市场上保持先机。 您的腾飞,需要一个踏脚的平台,而我们愿意成为您走向成功的平台—让我们共同努力,成就您的IT职业生涯! 北大青鸟中山大学科苑中心结合培训中心的自身优势,携手"广州近千家企业"开设IT企业定向培养就业班,现正热招中,欢迎您的报读。 请相信:教育改变生活~~! 详情了解:QQ:457411385 电话:13450489218/020-84111371 肖老师 当面咨询地址:广州市海珠区(中山大学西门)海珠科技园七楼
中心网址:www.gz-accp.com
|