我正在思考模型背后的asp.net 2.0代码。
将一个按钮拖到我的 Default.aspx 页面后,我在 Default.aspx.designer.cs 文件中得到以下声明:
public partial class _Default {
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
protected global::System.Web.UI.WebControls.Button Button1;
}
现在可以在 Default.aspx.cs 文件中编写以下代码:
protected void Button1_Click(object sender, EventArgs e)
{
Button1.Text = "clicked!";
}
但是我想知道,我得到的只是Button类型的Button1变量的声明,它还没有 instanciated ,这个代码怎么能运行而没有触发空引用异常?
我认为某处必须存在这样的代码:
Button1 = new Button();
但这段代码在哪里?这段代码什么时候执行?是谁执行的?
非常感谢......
我在一个神秘的位置找到了2个自动生成的文件 C:\ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ Temporary ASP.NET Files \ root \ edd9f4a1 \ 7f113408 ,它们是:
App_Web_x_swwj6s.1.cs
App_Web_x_swwj6s.0.cs
我在App_Web_x_swwj6s.0.cs文件中找到了如下代码:
private global::System.Web.UI.WebControls.Button @__BuildControlButton1()
{
global::System.Web.UI.WebControls.Button @__ctrl;
@__ctrl = new global::System.Web.UI.WebControls.Button();
//....
this.Button1 = @__ctrl;
return @__ctrl;
}
此方法在以下代码中调用:
private global::System.Web.UI.HtmlControls.HtmlForm @__BuildControlform1()
{
//....
global::System.Web.UI.WebControls.Button @__ctrl1;
@__ctrl1 = this.@__BuildControlButton1();
//......
}
最后,在以下方法中调用上述代码:
protected override void FrameworkInitialize()
所以我相信 FrameworkInitialize()方法是将控件引用绑定到控件实例的脏工作者
为了证明这一点,我故意在我的代码隐藏文件中编写以下代码:
protected override void FrameworkInitialize()
{
this.Button1 = null;
}
我希望单击按钮时会出现Null Reference Exception,但奇怪的是,整个网站运行顺畅。
我在aspx文件中声明的所有控件都是使用FrameworkInitialize()方法创建的吗?为什么在上面的场景中没有空引用异常?
再次感谢。
我想我可能会找到解释,我检查了ASP.NET使用.NET反射器生成的最终页面类。它的推导关系是这样的:
default_aspx class(代表页面的终极类)< --- _Default 类(类后面的代码)< --- System.Web.UI 。第
在default_aspx类中,我发现了这个:
protected override void FrameworkInitialize()
{
base.FrameworkInitialize(); // Button1=null is executed here.
this.__BuildControlTree(this); // Here Button1 is STILL set to an instance.
base.AddWrappedFileDependencies(__fileDependencies);
base.Request.ValidateInput();
}
所以,这可以解释为什么我将Button1设置为null的意图失败。
现在,我的问题是,必须在页面生命周期的最开始时调用FrameworkInitialize()方法,这样我们才能在页面上使用控件。
来自here:
HTTP页面处理程序类是 完全确定,ASP.NET运行时 调用处理程序的ProcessRequest 处理请求的方法。 通常,没有必要改变 这个方法的实现就像它一样 由Page class提供。
此实现从调用开始 方法FrameworkInitialize,其中 构建页面的控件树。 该方法是受保护的和虚拟的 TemplateControl的成员 class - Page本身的类 派生。任何动态生成的 .aspx资源的处理程序 覆盖FrameworkInitialize。在这 方法,整个控制树为 页面已建成。
答案 0 :(得分:3)
在触发OnLoad等事件之前,页面及其控件(在本例中包括您的按钮)由webforms“视图引擎”实例化。
否则,您必须拥有ISAPI过滤器或类似设备拦截请求,并在任何事件被触发之前创建页面对象及其控件。我认为这就是ASP.NET ISAPI DLL的功能。
我没有试过这个,但你可以在页面的构造函数中设置一个断点,在创建任何东西之前看到::Controls[]
列表,我希望它是空的(但页面生命周期)我在下面提供的循环链接会有更好的解释。)
答案 1 :(得分:3)
那么你现在究竟想要得到什么答案......对我来说,看起来你的大部分问题都是你自己回答的? :)
关于FrameworkInitialize
最简单的方法,如果你启动Reflector并查看代码。代码是法律! :)在这里你会看到System.Web.UI.TemplateControl.FrameworkInitialize()
将调用名为System.Web.Compilation.BuildResultNoCompileTemplateControlFrameworkInitialize(TemplateControl)
的内部方法,该方法正在对控制树进行实际初始化。这意味着覆盖FrameworkInitialize()
并将Button1
设置为null没有任何效果,因为该代码最终会在控件树初始化之前运行。