好的,我正在尝试了解如何最好地处理 ViewState
,以便使用 C# 以编程方式设置默认值。据我所知,ViewState
隐藏字段的构建基于触发 OnInit
事件后设置的每个值。我不清楚的是,使用控件的构造函数或 OnInit
事件设置默认值之间是否存在差异。
public MyControl(){
this.Text = "SomeDefaultValue";
}
对比
protected override void OnInit(EventArgs e){
this.Text = "SomeDefaultValue";
}
我看到一些地方建议在给定属性的 get
中测试 null
的 ViewState 值,如下所示:
public string Text {
get {
return this.ViewState["Text"] == null ?
"SomeDefaultValue" :
this.ViewState["Text"] as string;
}
set { this.ViewState["Text"] = value; }
}
我不喜欢这样,因为它使清除值变得困惑。
那么,使用构造函数与 OnInit
设置默认 ViewState
值之间在功能上有什么区别吗?
最佳答案
在最小化 ViewState 方面,没有区别,因为 ViewState 在 OnInit
方法运行后开始跟踪。
但是,存在一些功能差异:在控件初始化之前,您无法访问其他属性,如 Page
。出于这个原因,我通常更喜欢使用 OnInit
或一些绑定(bind)到 Init
事件的处理程序。
此外,在覆盖 OnInit 时要小心:您应该调用 base.OnInit()
以确保仍然调用 Init 事件的其他事件处理程序。
我强烈建议您阅读这篇关于该主题的优秀文章:http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx
编辑
需要说明的是,ViewState 在 给定控件 运行 OnInit
方法后开始跟踪给定控件。因此,在给定的示例中,您可以像这样安全地覆盖 OnInit
:
protected override void OnInit(EventArgs e){
this.Text = "SomeDefaultValue"; // Make sure this happens before base.OnInit
base.OnInit();
}
这是有效的,因为 Text
属性将值保存到此控件的 ViewState 。但是,假设您有另一个子控件(我将使用 Label
作为示例)。在调用控件的 OnInit
方法时,该标签的 OnInit
已经运行。因此,如果您想更改标签的文本值,则需要在该标签的 OnInit 阶段(或更早)执行此操作。
您可以在当前控件的构造函数中执行此操作:
public MyControl(){
this.Label.Text = "SomeDefaultValue";
}
...但是如前所述,您将无权访问外部控制结构,这在某些情况下可能是必需的。在这些情况下,一个好的替代方法是在标签本身上使用 Init
事件处理程序。您可以在构造函数中连接事件处理程序本身:
public MyControl(){
this.Label.Init +=
(sender, e) => this.Label.Text =
((TextBox)Page.FindControl("SomeControl")).Text;
}
...但这只有在控件被直接声明为您的类的成员时才有效。如果标签在模板内(如在 Repeater 中),您需要使用标记将其连接起来:
<asp:Label runat="server" OnInit="Label_Init" />
代码隐藏:
public void Label_Init(object sender, EventArgs e)
{
var label = (Label)sender;
label.Text = ((TextBox)Page.FindControl("SomeControl")).Text;
}
后一个示例的优点是可以在我能想到的几乎所有情况下工作,但它需要更多的样板代码以及标记的更改。因此,请根据您的具体情况选择毒药。
关于c# - 最小化 ASP.Net 中的 ViewState 大小,在构造函数中初始化控件值与 OnInit 之间有区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5638875/