怎样编写简单的Web Custom Control

原创 2003年12月19日 23:15:00
 

怎样编写简单的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>");
  }
 }
}

 

如何写一个简单的webserver(一):最简实现

本文主要讲述如何用C/C++写一个简单的支持并发的web服务器,并不考虑服务器的健壮性、安全性、性能等一系列因素。 在本文中,该服务器仅支持GET请求。 项目地址:https://github.c...
  • imjtrszy
  • imjtrszy
  • 2016年12月11日 22:42
  • 6509

【Java学习笔记】如何写一个简单的Web Service

【Java学习笔记】如何写一个简单的Web Service 作者:gnuhpc  出处:http://www.cnblogs.com/gnuhpc/ 本Guide利用Eclipse以及Ant...
  • sundancer_lilong
  • sundancer_lilong
  • 2016年05月23日 11:29
  • 1231

自己写一个简单的Web服务器(附Demo)

一、什么是Web服务器? 先来写个例子亲身体验一下。下面的示例代码演示了如何通过 java.net.Socket 与 java.net.ServerSocket这两个重要的类创建一个简单...
  • chuan3676
  • chuan3676
  • 2015年03月22日 22:52
  • 2216

windows metro中Custom Control的开发和使用

在windows metro应用程序开发中,如果想自己的应用程序更加个性独特,或者需要实现的控件windows并不自带,那么除了一些简单一些的可以使用User Control外,对于一些复杂的我们还可...
  • anvien
  • anvien
  • 2013年08月03日 01:16
  • 524

zz - transcript of Defining and Using Shared Resources in a Custom Control Library

the original link is http://blogs.msdn.com/b/wpfsdk/archive/2007/06/08/defining-and-using-shared-res...
  • redalert2c
  • redalert2c
  • 2012年05月16日 12:09
  • 249

ios开发(十六)custom control

http://www.raywenderlich.com/36288/how-to-make-a-custom-control http://hubpages.com/hub/iOS-Create-C...
  • wangeen
  • wangeen
  • 2013年12月11日 21:18
  • 1473

Custom Draw ListView Control(二) .

下一步就是添加NM_CUSTOMDRAW的消息处理通知消息。   通常,添加一个消息处理句柄可以简单的在类视图中的CListCtrlWithCustomDraw上右键点击,或者使用WizardBa...
  • wodesanmaoqian
  • wodesanmaoqian
  • 2011年11月29日 14:39
  • 830

经典 -Writing a UI Automation Provider for a Win32-based Custom Control

Do you have a complex custom control that you want to make programmatically accessible, but you aren...
  • djinglan
  • djinglan
  • 2011年08月05日 11:00
  • 1038

IOS Apps 开发(Swift)(6)——Implement a Custom Control(2)

前言:网上一直没有找到用Swift开发IOS的好的教程,所以找了官网的文档翻译一下算了。如有错误欢迎指正。 原文链接:Implement a Custom Control —————————————...
  • mcf171
  • mcf171
  • 2016年02月26日 14:42
  • 503

Custom Control进行多行列表控制CMultilineList类

翻译来源:https://www.codeproject.com/Articles/15480/Multi-line-List-Control 作者:Dave Calkins ...
  • greless
  • greless
  • 2017年06月16日 16:41
  • 330
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:怎样编写简单的Web Custom Control
举报原因:
原因补充:

(最多只允许输入30个字)