在ASP.NET中,有时可能需要从不同的页面控制另一个页面。这种方法的一个主要问题是服务器会在内存中加载请求的页面。因此,在同一时间,只能处于一个页面,比如Page1。可以在Page1中创建Page2的对象,但是无法获取关于控件的信息,因为只有在Page_Init触发时控件才会初始化,而只是创建了页面的对象,并没有涉及生命周期。
为了解决这个问题,.NET提供了许多类,这些类有助于动态编译页面,并且非常有用,如果想缓存页面以实现更快的访问和更好的用户体验。应该了解ASP.NET页面是在用户请求时编译并缓存以供后续使用的。
将讨论并使用的类是BuildManager类。让从Page1中计算Page2中的Panel控件数量。将使用反射来动态创建实例,这就是为什么需要页面的类型信息。这可以通过以下方式实现:
// 获取引用路径的编译类型
string pagePath = "~/Page2.aspx";
Type type = BuildManager.GetCompiledType(pagePath);
一旦有了类型,就可以继续使用以下方式创建Page2的实例:
Page myPage = (Page)Activator.CreateInstance(type);
上面的代码将创建页面实例,但如果尝试访问Page2的Controls集合,会发现它为0,这是因为只是调用了构造函数来创建实例。没有涉及页面生命周期,这是填充页面控件所必需的。要执行页面生命周期,将调用Page类上的ProcessRequest方法,如下所示:
myPage.ProcessRequest(HttpContext.Current);
现在可以访问控件集合并做想做的事情。
// 初始化计数为0
int count = 0;
// 获取引用路径的编译类型
string pagePath = "~/Page2.aspx";
Type type = BuildManager.GetCompiledType(pagePath);
// 如果类型为null,则无法确定页面类型
if (type == null)
throw new ApplicationException("Page " + pagePath + " not found");
Page myPage = (Page)Activator.CreateInstance(type);
myPage.ProcessRequest(HttpContext.Current);
foreach (Control control in myPage.Controls)
{
if (control is Panel)
++count;
if (control.HasControls())
CountControls(control, ref count);
}
private static void CountControls(System.Web.UI.Control control, ref int count)
{
foreach (System.Web.UI.Control childControl in control.Controls)
{
System.Web.UI.WebControls.WebControl webControl = childControl as System.Web.UI.WebControls.WebControl;
if (webControl != null)
{
if (webControl is System.Web.UI.WebControls.Panel)
++count;
if (webControl.HasControls())
CountControls(webControl, ref count);
}
}
}