当前位置:首页 > ASP.NET 控件开发教程(一)

ASP.NET 控件开发教程(一)

点击次数:1494  更新日期:2010-12-31
\n

很多朋友都在问.NET控件开发 到底有多难(看到很多博友发自己的一些控件,我在想自己开发的就有好几十个了,与其一个个发,不如直接讲给大家听如何开发的,同时在讲解的过程把一些控件发给大家呵呵),其实可以轻松的告诉大家有恒心就能成绩来着,最好的控件全部在你身边,想开发高效好用的空间那就必须参考微软本身优秀的控件.为此我们手头要有一个好的工具Reflector.exe,这个大名鼎鼎的Reflector 你还不知道的话,只能被笑话了(窃笑),好了 大家伙自己百度谷歌找下,然后继续我们的文章,对于控件的使用我初略的给.NET 控件使用开发人员分了一个等级:


\n

1. 会使用ASP.NET 控件(简单的自定义控件,还有服务器控件),对事件=其他知识完全没有概念


\n

2. 掌握了页面事件的初步框架,能在不同事件中处理控件逻辑


\n

3. 开发控件,运用属性以及理解HtmlTextWriter 输出的基本特性


\n

4. 开发复杂控件,整合CSS,JS 以及缓存,主题==各种功能的 综合性控件


\n

看看你自己处于那个阶段,是不是还停留在只会用用GridView ==控件的一些初级阶段呢?其实想摆脱现状就必须从整个页面事件去了解,对于页面事件我会在接下来的文章好好给大家分析来着.


\n

通过本文希望大家从控件开发中,深入理解 .NET 页面事件,以及各种控件开发中的设计模式(其实透过.NET FRAMEWORK中的Controls类的设计就能明白微软的意图),以及委托在事件中的使用,和一些基本的正则使用.当然最后是控件的完美开发咯


\n

废话不多说.先给大家分析一个 我们经常用到的控件ASP.NET Button 控件


\n

我们打开Reflector找到 System.Web.UI.WebControls这个命名控件,然后找到Button控件,我们展开
520)this.width=500″ border=0>


\n

520)this.width=500″ border=0>


\n



\n

找到Button 控件, 然后继续展开Button,


\n

我这里和大家讲讲分别是什么意思就好了 其他的大家自己去看了 不过不理解的 我们可以一起讨论,还可以为你解释一下,那些控件我基本通看了一下 嘿嘿


\n

Base Types 是他的基本类型,Derived Types 是他的派生类,红色的那些图标是她的 方法,带有手的图标是 属性,闪电的图标是 事件 ,.ctor() 就是构造函数 cctor 就是静态构造函数,EventClick ,和 EventCommand 是类成员 .好了 基本就这样了 大家有什么不明白的可以在这里提问,我也会及时回答的.其实 Button 控件包含的意义很深,看明白了 对以后的控件开发有很大的帮助


\n

比如他的
Code
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
bool useSubmitBehavior = this.UseSubmitBehavior;
if (this.Page != null)
{
this.Page.VerifyRenderingInServerForm(this);
}
if (useSubmitBehavior)
{
writer.AddAttribute(HtmlTextWriterAttribute.Type, “submit”);
}
else
{
writer.AddAttribute(HtmlTextWriterAttribute.Type, “button”);
}
PostBackOptions postBackOptions = this.GetPostBackOptions();
string uniqueID = this.UniqueID;
if ((uniqueID != null) && ((postBackOptions == null) || (postBackOptions.TargetControl == this)))
{
writer.AddAttribute(HtmlTextWriterAttribute.Name, uniqueID);
}
writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
bool isEnabled = base.IsEnabled;
string firstScript = string.Empty;
if (isEnabled)
{
firstScript = Util.EnsureEndWithSemiColon(this.OnClientClick);
if (base.HasAttributes)
{
string str3 = base.Attributes["onclick"];
if (str3 != null)
{
firstScript = firstScript + Util.EnsureEndWithSemiColon(str3);
base.Attributes.Remove(“onclick“);
}
}
if (this.Page != null)
{
string postBackEventReference = this.Page.ClientScript.GetPostBackEventReference(postBackOptions, false);
if (postBackEventReference != null)
{
firstScript = Util.MergeScript(firstScript, postBackEventReference);
}
}
}
if (this.Page != null)
{
this.Page.ClientScript.RegisterForEventValidation(postBackOptions);
}
if (firstScript.Length > 0)
{
writer.AddAttribute(HtmlTextWriterAttribute.onclick, firstScript);
if (base.EnableLegacyRendering)
{
writer.AddAttribute(“language”, “javascript”, false);
}
}
if (this.Enabled && !isEnabled)
{
writer.AddAttribute(HtmlTextWriterAttribute.Disabled, “disabled”);
}
base.AddAttributesToRender(writer);
}


\n

AddAttributesToRender这个方法 就很好的展示给大家 ASP.NET 只如何处理INPUT 各种属性的呢.
下面分享我开发工程中的一个控件
这个控件是支持Url 分页的
当然 原理 是利用IList 的索引 取不同”页”的数据 对于偷懒和后台管理很方便,至于前台的分页我想你更喜欢用存储过程 的ROW_NUMBER() 和 IDENTITY 方案来分页吧


\n


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;
using System.Collections;


\n

namespace YSMV.XWShop1B2C.Control
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:YsmvRepeater runat=\\"server\\" AllowPage=\\"true\\" PageSize=\\"10\\" ShowPage=\\"true\\"></{0}:YsmvRepeater>")]
public class YsmvRepeater : Repeater
{

//Static param
private static readonly Regex RX;
private static readonly object EventPageChanged;


\n

static YsmvRepeater()
{
RX = new Regex(@”^&page=\\d+”, RegexOptions.Compiled);
EventPageChanged = new object();
}


\n

//Static constants
protected const string HTML1 = “<table cellpadding=0 cellspacing=0 class=’inputTable’><tr><td colspan=2>”;
protected const string HTML2 = “</td></tr><tr><td class=paging align=left>”;
protected const string HTML3 = “</td><td align=right class=paging>”;
protected const string HTML4 = “</td></tr></table>”;
private const string LINK_PREV = “<a href=?page={0}><&nbsp;Previous</a>”;
private const string LINK_MORE = “<a href=?page={0}>More&nbsp;></a>”;
private const string KEY_PAGE = “page”;
private const string COMMA = “?”;
private const string AMP = “&”;


\n

protected string emptyText;
private IList dataSource;
private int pageSize = 10;
private int currentPageIndex;
private int itemCount;
private bool allowPage = false;
private bool showPage = true;


\n

[Browsable(true)
, Category("Appearance"),
DefaultValue(true),
Description("是否显示翻页链接")
]
public bool ShowPage
{
get { return showPage; }
set { showPage = value; }
}
[Browsable(true),
Category("Appearance"),
DefaultValue(true),
Description("是否允许分页")]
public bool AllowPage
{
get { return allowPage; }
set { allowPage = value; }
}
[Browsable(true),
Category("Appearance"),
DefaultValue(10),
Description("每页显示的数量")
]
public int PageSize
{
get { return pageSize; }
set { pageSize = value; }
}
[Browsable(true),
Category("Appearance"),
DefaultValue(""),
Description("无记录时候显示的内容")]
public string EmptyText
{
set { emptyText = value; }
}
override public object DataSource
{
set
{
//This try catch block is to avoid issues with the VS.NET designer
//The designer will try and bind a datasource which does not derive from ILIST
try
{
dataSource = (IList)value;
ItemCount = dataSource.Count;
}
catch
{
dataSource = null;
ItemCount = 0;
}
}
}
protected int PageCount
{
get { return (ItemCount – 1) / pageSize; }
}


\n

virtual public int ItemCount
{
get { return itemCount; }
set
{itemCount = value;}
}


\n

virtual public int CurrentPageIndex
{
get { return currentPageIndex; }
set { currentPageIndex = value; }
}


\n

public void SetPage(int index)
{
//OnPageIndexChanged(new DataGridPageChangedEventArgs(null, index));
OnPageIndexChanged(new GridViewPageEventArgs(index));
}


\n

override protected void OnLoad(EventArgs e)
{
if (Visible)
{
string page = Context.Request[KEY_PAGE];
int index = (page != null) ? int.Parse(page) : 0;
SetPage(index);
}
}


\n

/// <summary>
/// Overriden method to control how the page is rendered
/// </summary>
/// <param name=”writer”></param>
override protected void Render(HtmlTextWriter writer)
{


\n

//Check there is some data attached
string page = Context.Request[KEY_PAGE];
int index = (page != null) ? int.Parse(page) : 0;
if (ItemCount == 0)
{
writer.Write(emptyText);
return;
}
//Mask the query
string query = Context.Request.Url.Query.Replace(COMMA, AMP);
query = RX.Replace(query, string.Empty);


\n

// Write out the first part of the control, the table header
writer.Write(HTML1);


\n

// Call the inherited method
base.Render(writer);


\n

// Write out a table row closure
writer.Write(HTML2);


\n

//Determin whether next and previous buttons are required
//Previous button?
if (currentPageIndex > 0)
{
if (ShowPage)
writer.Write(string.Format(LINK_PREV, (currentPageIndex – 1) + query));
}


\n

//Close the table data tag
writer.Write(HTML3);


\n

//Next button?
if (currentPageIndex < PageCount)
{
if (ShowPage)
writer.Write(string.Format(LINK_MORE, (currentPageIndex + 1) + query));
}


\n

//Close the table
writer.Write(HTML4);
}


\n

override protected void OnDataBinding(EventArgs e)
{
if (!allowPage)
{
base.DataSource = dataSource;
base.OnDataBinding(e);
return;
}
//Work out which items we want to render to the page
int start = CurrentPageIndex * pageSize;
int size = Math.Min(pageSize, ItemCount – start);


\n

IList page = new ArrayList();


\n

//Add the relevant items from the datasource
for (int i = 0; i < size; i++)
page.Add(dataSource[start + i]);


\n

//set the base objects datasource
base.DataSource = page;
base.OnDataBinding(e);


\n

}


\n

//public event DataGridPageChangedEventHandler PageIndexChanged;
public event GridViewPageEventHandler PageIndexChanged
{
add
{
Events.AddHandler(EventPageChanged, value);
}
remove
{
Events.RemoveHandler(EventPageChanged, value);
}
}
virtual protected void OnPageIndexChanged(GridViewPageEventArgs e)
{
GridViewPageEventHandler pagehandler = (GridViewPageEventHandler)Events[EventPageChanged];
if (pagehandler != null)
pagehandler(this, e);
}
}
}
代码已经加了注释,细心的朋友 可能发现和 PETSHOP 中的控件很相似 ,对,我是用那个修改的,我优化了他的事件private static readonly object EventPageChanged; 呵呵 ,好的 大家期待我的下个作品吧.


\n


来源:http://www.cnblogs.com/bhtfg538

\n