分享
 
 
 

怎样编写简单的Web Custom Control

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

怎样编写简单的Web Custom Control

作者:Robert

联系方式:Robert_luoqing@hotmail.com

Web Custom Control的函数调用序列图(本人根据调用过程自制的序列图,有不对的地方望指正):

注意:

1、在序列图的区域(1)中的函数执行顺序是不能确定的。

2、区域(2)内的函数是当第一次用到内部的子控件时就会调用到该区域内的函数,用来保证在调用子控件之前已把子控件初始化了;另外,一定要注意到CreateChildrenControls函数,在调用过程中,如果不控制ChildrenControlsCreated变量,则系统会保证只执行一次(即调用多次EnsureChildControls函数,CreateChildrenControls也只会调一次,因为当调用一次后,ChildrenControlsCreated被设为true,以后执行EnsureChildControls就不会调用到CreateChildrenControls函数了)。

3、在SaveViewState函数的下面千万不要对ViewState赋值,因为系统在SaveViewState函数内把ViewState中的值写入(序列化)到Page中去了,如果在该函数之后更改了ViewState变量,则值是不会被序列化的。

4、INamingContainer指示接口的作用:上面没有标出,该接口可以使在CreateChildrenControls中创建的子控件具有保持PostBackData值的效果。比如:在CreateChildrenControls内有下面一段代码:

TextBox m_text=new TextBox();

m_text.Text="Test";

m_text.AutoPostBack=true;

this.Controls.Add(m_text);

base.CreateChildControls ();

第一次执行的时m_text内的值是“Test”,当用户在界面中把该文本框的值改为“Secord”以后,如果该自定义web控件实现了INamingContainer接口,Post back后值仍然是“Secord”,如果没有实现该接口,则值为“Test”(我只注意到这个差别,大家可以试一下,找出其他的差别);

5、在编写Web Custom Control时,除LoadViewState,SaveViewState这两个地方用使用ViewState进行序列化和反序列化外,其他的地方最好用类的非公有变量代替,这样有几点好处:1、代码清晰(避免了即有ViewState又有变量,有时会使人糊涂);2、避免了多次类型转换;3、清楚明了的知道有几个变量被列化(当然这在写用户Web控件的时然也一样)。

6、如果要在Web Custom Control内引发事件的话(非子控件引发的事件),一定要实现IPostBackEventHandler接口,下段代码可以说明怎样引发事件:

protected override void Render(HtmlTextWriter output)

{

output.Write("<a href=javascript:"+this.Page.GetPostBackEventReference(this,"first")+">postback</a>");

base.Render(output);

}

这段代码会输入“postback”的一个链接,当点击时就会把内容提交到服务器,这时就可以在RaisePostBackEvent(string eventArgument)函数内接收事件了,其中eventArgument是与Page.GetPostBackEventReference的第二个参数相对应。

由于时间有限,对于其他的接口或功能希望大家自己体会。

下面有一段数据导行栏的代码做为参考。

//****************************************************************

/*

* 要求属性:

* 1、记录总数

* 2、每页显示记录数

* 3、当前页数

*

*该数据导行样的功能:

*1、要求提供记录总数,记录数,当前页数的功能

*2、要求提供上一页,下一页,首页,尾页的导行按钮,并要给出导行事件

*3、要求根据当前页来显示导行按钮的显示状态。

*4、要求客户只输入属性一次,以后要求系统自动维护各属性的变化。

*5、要求控件对属性的序列化

* */

using System;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.ComponentModel;

namespace CustomerTest

{

public delegate void DataBarClick(object e,int number);

/// <summary>

/// Summary description for DataBar.

/// </summary>

[DefaultProperty("TotalRecord"),

ToolboxData("<{0}:DataBar NumberPerPage=20 TotalRecord=0 CurrentPage=1 runat=server></{0}:DataBar>")]

public class DataBar : System.Web.UI.WebControls.WebControl,INamingContainer

{

protected System.Web.UI.WebControls.LinkButton LinkButtonPreview;

protected System.Web.UI.WebControls.LinkButton LinkButtonNext;

protected System.Web.UI.WebControls.LinkButton LinkButtonLast;

protected System.Web.UI.WebControls.LinkButton LinkButtonFirst;

private bool m_Design=true;

protected int m_TotalRecord;//总记录数

protected int m_CurrentPage=1;//当前显示的页号

protected int m_NumberPerPage;//每页显示记录数

//建立寻行数据页数的事件

public event DataBarClick databarClick;

/// <summary>

/// Get或Set数据的总记录数

/// </summary>

[Bindable(true),

Category("Data"),

DefaultValue(0)]

public int TotalRecord

{

get

{

return this.m_TotalRecord ;

}

set

{

if(value<0)

throw new Exception("给出的总记录数不能少于0");

this.m_TotalRecord=value;

}

}

/// <summary>

/// Get或Set当前显示的页号

/// </summary>

[Bindable(true),

Category("Data"),

DefaultValue(1)]

public int CurrentPage

{

get

{

return this.m_CurrentPage;

}

set

{

if(value<1)

throw new Exception("给出的当前页不能少于1");

this.m_CurrentPage = value;

}

}

/// <summary>

/// Get或Set每页显示记录数

/// </summary>

[Bindable(true),

Category("Data"),

DefaultValue(20)]

public int NumberPerPage

{

get

{

return this.m_NumberPerPage;

}

set

{

if(value<1)

throw new Exception("每页显示的记录数不能少于1");

this.m_NumberPerPage = value;

}

}

protected override void CreateChildControls()

{

Table l_table=new Table();//建立外层的Table

TableRow l_tbrow=new TableRow();//只有一行

l_table.Rows.Add(l_tbrow);

TableCell l_tbcell=new TableCell();//建立第一个列的内容

l_tbrow.Controls.Add(l_tbcell);

l_tbcell.Wrap=false;

LinkButtonFirst =new System.Web.UI.WebControls.LinkButton();

LinkButtonFirst.ID="LinkButtonFirst";

LinkButtonFirst.Text="首页";

LinkButtonFirst.Click+=new EventHandler(Guid_Click);

l_tbcell.Controls.Add(LinkButtonFirst);

l_tbcell=new TableCell();//建立"|"

l_tbrow.Controls.Add(l_tbcell);

l_tbcell.Text=" | ";

l_tbcell=new TableCell();//建立第二个列的内容

l_tbrow.Controls.Add(l_tbcell);

l_tbcell.Wrap=false;

LinkButtonPreview =new System.Web.UI.WebControls.LinkButton();

LinkButtonPreview.ID="LinkButtonPreview";

LinkButtonPreview.Text="上一页";

LinkButtonPreview.Click+=new EventHandler(Guid_Click);

l_tbcell.Controls.Add(LinkButtonPreview);

l_tbcell=new TableCell();//建立"|"

l_tbrow.Controls.Add(l_tbcell);

l_tbcell.Text=" | ";

l_tbcell=new TableCell();//建立第三个列的内容

l_tbrow.Controls.Add(l_tbcell);

l_tbcell.Wrap=false;

LinkButtonNext =new System.Web.UI.WebControls.LinkButton();

LinkButtonNext.ID="LinkButtonNext";

LinkButtonNext.Text="下一页";

LinkButtonNext.Click+=new EventHandler(Guid_Click);

l_tbcell.Controls.Add(LinkButtonNext);

l_tbcell=new TableCell();//建立"|"

l_tbrow.Controls.Add(l_tbcell);

l_tbcell.Text=" | ";

l_tbcell=new TableCell();//建立第四个列的内容

l_tbrow.Controls.Add(l_tbcell);

l_tbcell.Wrap=false;

LinkButtonLast =new System.Web.UI.WebControls.LinkButton();

LinkButtonLast.ID="LinkButtonLast";

LinkButtonLast.Text="尾页";

LinkButtonLast.Click+=new EventHandler(Guid_Click);

l_tbcell.Controls.Add(LinkButtonLast);

this.Controls.Add(l_table);

base.CreateChildControls ();

}

private void Guid_Click(object sender, System.EventArgs e)

{

setGuide(sender);

if(this.databarClick!=null)

{

this.databarClick(this,this.m_CurrentPage);

}

}

/// <summary>

/// 用于激发databarClick事件

/// </summary>

public void OndatabarClick()

{

if(this.databarClick!=null)

{

this.databarClick(this,this.m_CurrentPage);

}

}

/// <summary>

/// 这是用来显示导行栏中每个元素的状态

/// </summary>

/// <param name="sender">表示是按的那一个导行栏元素的按钮,如果不是由导行栏触发,则传null值</param>

private void setGuide(object sender)

{

int m_iTotalPage = Convert.ToInt32(System.Math.Ceiling(Convert.ToDouble(this.m_TotalRecord)/Convert.ToDouble(m_NumberPerPage)));

if(m_iTotalPage<this.m_CurrentPage)

this.m_CurrentPage=1;

if(sender!=null)

{

if(((Control)sender).ID=="LinkButtonFirst")

{

this.m_CurrentPage=1;

}

if(((Control)sender).ID=="LinkButtonNext")

{

this.m_CurrentPage=this.m_CurrentPage+1;

}

if(((Control)sender).ID=="LinkButtonPreview")

{

this.m_CurrentPage=this.m_CurrentPage-1;

}

if(((Control)sender).ID=="LinkButtonLast")

{

this.m_CurrentPage=m_iTotalPage;

}

}

this.LinkButtonFirst.Enabled=!(this.m_CurrentPage==1);

this.LinkButtonPreview.Enabled=!(this.m_CurrentPage==1);

this.LinkButtonLast.Enabled=!(this.m_CurrentPage==m_iTotalPage);

this.LinkButtonNext.Enabled=!(this.m_CurrentPage==m_iTotalPage);

}

protected override void OnLoad(EventArgs e)

{

this.m_Design=false;

base.OnLoad (e);

}

protected override void Render(HtmlTextWriter writer)

{

if(this.m_Design)

writer.Write("数据导行栏控件");

base.Render (writer);

}

protected override void LoadViewState(object savedState)

{

base.LoadViewState (savedState);

/*

* 在这里用于变量的反序列化,即从ViewState中取回

* 变量的值。

* */

this.m_CurrentPage=(int)this.ViewState["CurrentPage"];

this.m_NumberPerPage=(int)this.ViewState["NumberPerPage"];

this.m_TotalRecord=(int)this.ViewState["TotalRecord"];

}

protected override object SaveViewState()

{

/*

*这里用于把变量序列化,以使PostBack时进行恢复。

* */

this.ViewState["CurrentPage"]=this.m_CurrentPage;

this.ViewState["NumberPerPage"]=this.m_NumberPerPage;

this.ViewState["TotalRecord"]=this.m_TotalRecord;

return base.SaveViewState ();

}

protected override void OnPreRender(EventArgs e)

{

this.setGuide(null);

base.OnPreRender (e);

}

}

}

//**********************************************************************************

测试码:

Test.aspx

<%@ Register TagPrefix="test" NameSpace="CustomerTest" Assembly="TestDataBar" %>

<%@ Page language="c#" Codebehind="Test.aspx.cs" AutoEventWireup="false" Inherits="TestDataBar.Test" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<HTML>

<HEAD>

<title>Test</title>

<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">

<meta name="CODE_LANGUAGE" Content="C#">

<meta name="vs_defaultClientScript" content="JavaScript">

<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">

</HEAD>

<body MS_POSITIONING="GridLayout">

<form id="Form1" method="post" runat="server">

<test:DataBar runat="server" id="stDBar"></test:DataBar>

<FONT face="宋体"></FONT>

</form>

</body>

</HTML>

Test.aspx.cs

using System;

using System.Collections;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Web;

using System.Web.SessionState;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

namespace TestDataBar

{

/// <summary>

/// Summary description for Test.

/// </summary>

public class Test : System.Web.UI.Page

{

protected CustomerTest.DataBar stDBar;

private void Page_Load(object sender, System.EventArgs e)

{

if(!this.IsPostBack)

{

this.stDBar.TotalRecord=100;

this.stDBar.NumberPerPage=15;

this.stDBar.CurrentPage=1;

}

}

#region Web Form Designer generated code

override protected void OnInit(EventArgs e)

{

//

// CODEGEN: This call is required by the ASP.NET Web Form Designer.

//

InitializeComponent();

base.OnInit(e);

}

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

this.stDBar.databarClick += new CustomerTest.DataBarClick(this.stDBar_databarClick);

this.Load += new System.EventHandler(this.Page_Load);

}

#endregion

private void stDBar_databarClick(object e, int number)

{

this.Response.Write("当前页是:第"+number.ToString()+"<br>");

this.Response.Write("总记录数是:"+this.stDBar.TotalRecord.ToString()+"<br>");

this.Response.Write("每页记录数是:"+this.stDBar.NumberPerPage.ToString()+"<br>");

}

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有