我正在尝试编写一个动态加载给定页面控件集合的方法,以便我可以遍历它并创建驻留在页面上的某些类型控件的列表。我的想法是,对于从特定页面类继承的任何页面,我想编译具有某些属性的可编辑字段列表。这一切都发生在这些页面之外(在允许用户管理这些其他页面的不同页面上)。
我尝试了以下两种情况:
BasePage page = (BasePage)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(string.Format("~/Pages/{0}/Manage.aspx", type.ToString()), typeof(BasePage));
IHttpHandler handler = PageParser.GetCompiledPageInstance(string.Format("~/Pages/{0}/Manage.aspx", type.ToString()), Context.Server.MapPath(string.Format("~/Pages/{0}/Manage.aspx", type.ToString())), HttpContext.Current);
BasePage page = handler as BasePage;
在这两种情况下,页面变量都会启动,但控件集合是空白的,可能是因为这两种方法都只加载代码隐藏而不是加载标记。如何动态加载页面的控件集合?
答案 0 :(得分:0)
我不会搞乱页面生命周期。让ASP.NET自己管理控件层次结构,并使用一些递归逻辑来检查页面上的控件:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
FindPanelControls(Page);
}
}
private void FindPanelControls(Control ctrl)
{
if (ctrl.HasControls())
{
foreach (var childCtrl in ctrl.Controls.OfType<WebControl>())
{
//check for certain attributes
if (childCtrl is Panel)
Response.Write(childCtrl.ID);
//recursively call the function for this control
FindPanelControls(childCtrl);
}
}
}
答案 1 :(得分:0)
你过于复杂了;只需通过Page.Controls集合递归循环,并检查您感兴趣的控件类型。看看这些早期的问题:
答案 2 :(得分:0)
我遇到了在运行时需要从页面B评估页面A的控件的完全相同的要求。
在整个生命周期中运行Page还需要一个额外的步骤。我们只需要调用Page.ProcessRequest()方法。 Page.ProcessRequest Method (MSDN)。该方法对Intellisense隐藏。
在此之后,您将能够访问页面中的控件:
Page page = (Page)BuildManager.CreateInstanceFromVirtualPath("~/MyPage.aspx", typeof(Page));
page.ProcessRequest(HttpContext.Current);
如果您的页面有母版页,则需要深入了解母版页的占位符。
请务必注意微软的评论:
“你不应该叫这个方法。”
“此API支持.NET Framework基础结构,不能直接在您的代码中使用。”
我还不知道这样做是否会产生任何不利影响。
编辑:在页面中执行页面可能会导致无数问题,所以我的方向略有不同。
使用HTML Agility Pack,我们可以加载* .aspx文件并非常容易地递归遍历其节点。如果我们想在页面上找到所有asp按钮,例如:
private static void FindAllButtonControls(HtmlNodeCollection htmlNodeCollection, List<HtmlNode> controlNodes)
{
foreach (HtmlNode childNode in htmlNodeCollection)
{
if (childNode.Name.Equals("asp:button"))
{
controlNodes.Add(childNode);
}
else
{
FindAllButtonControls(childNode.ChildNodes, controlNodes);
}
}
}
public static List<HtmlNode> FindButtonControlsAtVirtualPath(String path)
{
HtmlAgilityPack.HtmlDocument aspx = new HtmlAgilityPack.HtmlDocument();
aspx.OptionFixNestedTags = true;
aspx.Load(HttpContext.Current.Server.MapPath(path));
List<HtmlNode> controlNodes = new List<HtmlNode>();
FindAllButtonControls(aspx.DocumentNode.ChildNodes, controlNodes);
return controlNodes;
}