今天在开发CN.Text的过程中,我遇到了这样一个问题:当我通过<%# DataBinder.EvalContainer.DataItem,"Title") %>给一个控件的属性赋值时, 运行结果却显示这个属性没有被赋值,而我将<%# DataBinder.EvalContainer.DataItem,"Title") %>改成普通的字符串却很正常。这个属性是很简单的一个属性,它表示控件的标题,在控件中只要显示这个属性值就行了。.Text中提供的这个控件是在OnInit中显示这个属性值的。而我只要将显示属性值的代码移至OnPreRender(EventArgs e)或者OnLoad(EventArgs e)中问题就解决了。
下面我用一个简单的例子详细描述一下这个问题。
首先,我们定义一个简单的用户控件:
public
class
MyControl : System.Web.UI.UserControl
{
private string _text="Text is not be set";
public string Text
{
get
{
return _text;
}
set
{
_text=value;
}
}
Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
/**//// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器
/// 修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void Page_Load(object sender, System.EventArgs e)
{
Response.Write(Text);
}
}
{
private string _text="Text is not be set";
public string Text
{
get
{
return _text;
}
set
{
_text=value;
}
}
Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
/**//// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器
/// 修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void Page_Load(object sender, System.EventArgs e)
{
Response.Write(Text);
}
}
这个控件很简单,就是将属性Text的值显示出来。
<
asp:Repeater
id
="Repeater1"
runat
="server"
>
< ItemTemplate >
< uc1:MyControl id ="MyControl1" runat ="server" Text ='<%# "HelloWorld" % > '> </ uc1:MyControl >
</ ItemTemplate >
</ asp:Repeater >
< ItemTemplate >
< uc1:MyControl id ="MyControl1" runat ="server" Text ='<%# "HelloWorld" % > '> </ uc1:MyControl >
</ ItemTemplate >
</ asp:Repeater >
private
void
Page_Load(
object
sender, System.EventArgs e)
{
ArrayList al=new ArrayList();
al.Add(1);
al.Add(2);
Repeater1.DataSource=al;
Repeater1.DataBind();
}
{
ArrayList al=new ArrayList();
al.Add(1);
al.Add(2);
Repeater1.DataSource=al;
Repeater1.DataBind();
}
运行代码,结果当然是正常的。
现在我们将Response.Write(Text);移到OnInit中
override
protected
void
OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
Response.Write(Text);
InitializeComponent();
base.OnInit(e);
}
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
Response.Write(Text);
InitializeComponent();
base.OnInit(e);
}
运行结果却显示“Text is not be set”, 在执行OnInit时, Text还没有被赋值。而我们只要将Response.Write(Text);移至OnLoad中就能正常显示。
protected
override
void
OnLoad(EventArgs e)
{
Response.Write(Text);
base.OnLoad (e);
}
{
Response.Write(Text);
base.OnLoad (e);
}
也就是说, Text是在OnInit之后,OnLoad之前被赋值的。
这就说明Text='<%# "HelloWorld" %>'与Text="HelloWorld"执行的时间是不同的。所以我们在设计控件时,就要注意这一点,假如你想你写的控件支持运行期数据绑定,就避免在OnInit中处理相应的属性值。