通过代码加载页面的控件集合

时间:2012-04-04 21:19:20

标签: c# asp.net

我正在尝试编写一个动态加载给定页面控件集合的方法,以便我可以遍历它并创建驻留在页面上的某些类型控件的列表。我的想法是,对于从特定页面类继承的任何页面,我想编译具有某些属性的可编辑字段列表。这一切都发生在这些页面之外(在允许用户管理这些其他页面的不同页面上)。

我尝试了以下两种情况:

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;

在这两种情况下,页面变量都会启动,但控件集合是空白的,可能是因为这两种方法都只加载代码隐藏而不是加载标记。如何动态加载页面的控件集合?

3 个答案:

答案 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集合递归循环,并检查您感兴趣的控件类型。看看这些早期的问题:

ASP.Net / C#, Loop through certain controls on a page?

Loop through all controls on asp.net webpage

答案 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;
}