一起谈.NET技术,关于ASP.NET页面生命周期的整体把握

简介:   对于每一个.NET程序员,对于ASP.NET页面生命周期都有一定的了解和把握。关于一些细节方面请参考http://blog.sina.com.cn/s/blog_5f7aa2970100d5h4.html,内容比较详尽,本文将不再概述。

  对于每一个.NET程序员,对于ASP.NET页面生命周期都有一定的了解和把握。关于一些细节方面请参考http://blog.sina.com.cn/s/blog_5f7aa2970100d5h4.html,内容比较详尽,本文将不再概述。本文主要是从继承以及视图状态,事件,委托,容器控件以及子控件这些方面来把握和控制整体的页面生命周期。

  先看下下面4个相关页面的代码(为降低复杂度,很多代码被删减与精简,仅提供最基本的操作代码)。仅仅几个文件,先看下整体文件的布局,有一个整体的把握。

1

  (一)父类的相关事件以及处理

 
 
public class UserParentPage:System.Web.UI.Page
{
/// <summary>
/// 对回传数据的处理,以及其他内容的设置、获取
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
Core.Trace.TraceInfo(
" UserParentPage OnInit " );
base .OnInit(e);
// 编写相应的代码防止SQL注入
// System.Web.HttpContext.Current.Request.QueryString/Form
// 根据上下文对象来检测,以及做出相应的处理
// 以及其他一些内容的设置、控制等等
}

protected override void OnLoad(EventArgs e)
{
Core.Trace.TraceInfo(
" UserParentPage OnLoad " );
base .OnLoad(e);
// 编写相应的代码对整体页面的控制
}
}

  (二)用户控件(子控件)的相关内容

 
 
public partial class UserEventControl : System.Web.UI.UserControl
{
public delegate void ChangedHandler();
public event ChangedHandler Changed;
private void Page_Load( object sender, System.EventArgs e)
{
Core.Trace.TraceInfo(
" UserEventControl OnLoad " );
if ( ! Page.IsPostBack)
{
Core.Trace.TraceInfo(
" UserEventControl OnLoad !Page.IsPostBack==true " );
SetContent();
}
}
private void SetContent()
{
int len = 12 ,num = 2 ,perRowMaxCount = 8 ;
System.Text.StringBuilder table
= new System.Text.StringBuilder();
for ( int i = 0 ; i <= num; i ++ )
{
table.Append(
@" <table bordercolor='black' width='100%'><tr align='left'> " );
for ( int j = 0 ; j < perRowMaxCount; j ++ )
{
int p = i * perRowMaxCount + j;
if (p < len)
{
string paramValue = " param " + p.ToString();
string showValue = " show " + p.ToString();
table.Append(
string .Format( @" <td width='12.5%'>
<a href='javascript:__doPostBack(""{2}"",""{0}"")' CommandName=""{0}"" class='line'>
<font>{1}</font></a></td>
" , paramValue,showValue, lbtnShow.ClientID.Replace(
"
_lbtnShow " , " $lbtnShow " )));
}
else
{
table.Append(
string .Format( @" <td width='12.5%'></td> " ));
}
}
table.Append(
@" </tr></table> " );
}
lblShow.Text
= table.ToString();
}


public string CurrentID
{
set
{
ViewState[
" CurrentID " ] = value;
}
get
{
return ( string )ViewState[ " CurrentID " ];
}
}

protected override void OnInit(EventArgs e)
{
Core.Trace.TraceInfo(
" UserEventControl OnInit " );
InitializeComponent();
base .OnInit(e);
}


private void InitializeComponent()
{
this .lbtnShow.Click += new System.EventHandler( this .lbtnShow_Click);
this .Load += new System.EventHandler( this .Page_Load);
}
/// <summary>
/// 单击时将触发
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lbtnShow_Click( object sender, System.EventArgs e)
{
Core.Trace.TraceInfo(
" UserEventControl lbtnShow_Click " );
CurrentID
= Request.Form[ " __EVENTARGUMENT " ]; // 获取回传值
SetContent(); // 设置内容----因为有些内容被修改过,如样式什么的,本例忽略
Changed(); // 触发事件
}
}

  上面最主要的3点:

  (1)javascript:__doPostBack()和Request.Form["__EVENTARGUMENT"];__doPostBack()第一个参数必须用控件的name 而不是ID。控件名为将父控件ID用$符号连接起来的。第二个参数是传给控件的Value值。第一个参数对应 Request.Form["__EVENTTARGET"]; 第二个参数对应Request.Form["__EVENTARGUMENT"]。此函数是DOTNET 的服务器控件产生的,所以要使用此函数,必须整个页面上至少要有一个控件可以回传页面。其实,dotnet 服务器控件在页面上产生两个隐藏的控件一个名为__EVENTTARGET ,另一个名为__EVENTARGUMENT。

  (2)ViewState视图状态保存的是页面级别的内容。CurrentID = Request.Form["__EVENTARGUMENT"];

  (3)点击后将导致事件的触发(回传)。 Changed();

  (三)页面的事件与委托处理 <!-- #div_code img { border: 0px none; } -->

 
 
public partial class Default : Core.UserParentPage
{
protected void Page_Init( object sender, EventArgs e)
{
Core.Trace.TraceInfo(
" Default OnInit " );
}

protected void Page_Load(
object sender, EventArgs e)
{
Core.Trace.TraceInfo(
" Default Page_Load " );
userEventControl.Changed
+= new
UserControl.UserEventControl.ChangedHandler(userEventControl_Changed);
}


private void userEventControl_Changed()
{
Core.Trace.TraceInfo(
" Default userEventControl_Changed " );

string id = userEventControl.CurrentID;
ViewState[
" ID " ] = id; // 保存状态进行相应的处理
lblShow.Text = id;
}
}

  这一步最关键,利用userEventControl.Changed+=new UserControl.UserEventControl.ChangedHandler(userEventControl_Changed),当事件触发时,我们能够通过userEventControl_Changed()方法获取点击的value值,用视图状态保存该值,进而进行相应的操作(控制)。页面显示如下:

1

  (四)跟踪文件为当前目录下的trace.txt文件

 
 
public static class Trace
{
private static string logPath = HttpContext.Current.Request.PhysicalApplicationPath;
public static void TraceInfo( string information)
{
string path = logPath + @" trace.txt " ;
string sqltemp = DateTime.Now.ToString( " yyy-MM-dd hh:mm:ss fff " ) + " : "
+
information;
FileStream fs
= null ;
if ( ! File.Exists(path))
{
fs
= File.Create(path);
fs.Close();
}
StreamWriter sw
= new StreamWriter(path, true , Encoding.UTF8);
sw.WriteLine(sqltemp);
sw.Close();
}
}

  在每个页面上的事件中增加自定义跟踪,可以发现如下情况:Init和Load都在每个控件上递归方式发生,但它们发生的顺序是相反的。每个子控件的Init与Unload事件在其容器引发相应的事件之前发生。容器的Load事件是在其子控件的Load事件之前发生。

  trace.txt内容显示如下(生成页面的过程以及点击事件触发跟踪): <!-- #div_code img { border: 0px none; } -->     

 
 
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnInit
2010 - 11 - 23 02 : 26 : 29 828 : UserParentPage OnInit
2010 - 11 - 23 02 : 26 : 29 828 : Default OnInit
2010 - 11 - 23 02 : 26 : 29 828 : UserParentPage OnLoad
2010 - 11 - 23 02 : 26 : 29 828 : Default Page_Load
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad ! Page.IsPostBack == true
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad ! Page.IsPostBack == true
2010 - 11 - 23 02 : 26 : 31 171 : UserEventControl OnInit
2010 - 11 - 23 02 : 26 : 31 171 : UserParentPage OnInit
2010 - 11 - 23 02 : 26 : 31 171 : Default OnInit
2010 - 11 - 23 02 : 26 : 31 171 : UserParentPage OnLoad
2010 - 11 - 23 02 : 26 : 31 171 : Default Page_Load
2010 - 11 - 23 02 : 26 : 31 171 : UserEventControl OnLoad
2010 - 11 - 23 02 : 26 : 31 171 : UserEventControl OnLoad
2010 - 11 - 23 02 : 26 : 31 171 : UserEventControl lbtnShow_Click
2010 - 11 - 23 02 : 26 : 31 171 : Default userEventControl_Changed

  从前面的6句可以看出,子控件UserEventControl 的Init事件发生在UserParentPage 以及Default 的Init事件之前,而子控件UserEventControl 的Load事件发生在UserParentPage 以及Default 的Load事件之后。其中,父类UserParentPage 的事件发生在子类Default 的事件之前。

  注:

 
 
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad ! Page.IsPostBack == true
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad
2010 - 11 - 23 02 : 26 : 29 828 : UserEventControl OnLoad ! Page.IsPostBack == true

  这个地方明显有点不对劲,再反过去查看下子控件事件中的代码。发现

 
 
private void InitializeComponent()
{
this .lbtnShow.Click += new System.EventHandler( this .lbtnShow_Click);
this .Load += new System.EventHandler( this .Page_Load);
}

  多了这一行this.Load += new System.EventHandler(this.Page_Load); Load事件中再一次触发了子控件的Page_Load方法,因此注销掉该句。

  到此我们再看一下跟踪文件中的内容(将原有记录全清空),如下所示:

 
 
2010 - 11 - 23 02 : 46 : 11 281 : UserEventControl OnInit
2010 - 11 - 23 02 : 46 : 11 281 : UserParentPage OnInit
2010 - 11 - 23 02 : 46 : 11 281 : Default OnInit
2010 - 11 - 23 02 : 46 : 11 281 : UserParentPage OnLoad
2010 - 11 - 23 02 : 46 : 11 281 : Default Page_Load
2010 - 11 - 23 02 : 46 : 11 281 : UserEventControl OnLoad
2010 - 11 - 23 02 : 46 : 11 281 : UserEventControl OnLoad ! Page.IsPostBack == true
2010 - 11 - 23 02 : 46 : 13 265 : UserEventControl OnInit
2010 - 11 - 23 02 : 46 : 13 265 : UserParentPage OnInit
2010 - 11 - 23 02 : 46 : 13 265 : Default OnInit
2010 - 11 - 23 02 : 46 : 13 265 : UserParentPage OnLoad
2010 - 11 - 23 02 : 46 : 13 265 : Default Page_Load
2010 - 11 - 23 02 : 46 : 13 265 : UserEventControl OnLoad
2010 - 11 - 23 02 : 46 : 13 265 : UserEventControl lbtnShow_Click
2010 - 11 - 23 02 : 46 : 13 281 : Default userEventControl_Changed

  这里就分成了2次操作,第1次为加载显示的过程(1-7句),第2次为点击获取相应的值的过程(8-15句)。过程是差不多的,仅仅多了一个回传事件。这与上面总结的是一致的。

  总结

  通过父类、子类以及子控件之间的关系,加强对页面生命周期的理解,精简不必要的操作。通过事件和委托、视图状态能够很好的完成某些复杂的功能,具体应用本文将不再讲叙,仅仅是给读者一个引子。合理利用javascript:__doPostBack()和Request.Form["__EVENTARGUMENT"]能获得意想不到的效果。

  Init和Load都在每个控件上递归方式发生,但它们发生的顺序是相反的。每个子控件的Init与Unload事件在其容器引发相应的事件之前发生。容器的Load事件是在其子控件的Load事件之前发生。这个仅仅是本人以前实现的功能的一个精简版本,希望对各位有所帮助。

目录
相关文章
|
2月前
|
开发框架 算法 .NET
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
C#/.NET/.NET Core技术前沿周刊 | 第 15 期(2024年11.25-11.30)
|
2月前
|
开发框架 Cloud Native .NET
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
C#/.NET/.NET Core技术前沿周刊 | 第 16 期(2024年12.01-12.08)
|
3月前
|
自然语言处理 物联网 图形学
.NET 技术凭借其独特的优势和特性,为开发者们提供了一种高效、可靠且富有创造力的开发体验
本文深入探讨了.NET技术的独特优势及其在多个领域的应用,包括企业级应用、Web应用、桌面应用、移动应用和游戏开发。通过强大的工具集、高效的代码管理、跨平台支持及稳定的性能,.NET为开发者提供了高效、可靠的开发体验,并面对技术更新和竞争压力,不断创新发展。
137 7
|
3月前
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
57 5
|
3月前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
58 4
|
3月前
|
开发框架 .NET C#
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位。从企业应用到电子商务,再到移动开发,.NET 均展现出卓越性能,助力开发者提升效率与项目质量,推动行业持续发展。
55 4
|
3月前
|
机器学习/深度学习 人工智能 物联网
.NET 技术:引领未来开发潮流
.NET 技术以其跨平台兼容性、高效的开发体验、强大的性能表现和安全可靠的架构,成为引领未来开发潮流的重要力量。本文深入探讨了 .NET 的核心优势与特点,及其在企业级应用、移动开发、云计算、人工智能等领域的广泛应用,展示了其卓越的应用价值和未来发展前景。
82 5
|
3月前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
55 3
|
3月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
52 3
|
3月前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
67 3

热门文章

最新文章