加载页面';通过代码收集的控件

本文关键字:代码 控件 加载 | 更新日期: 2023-09-27 18:30:07

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

我已经尝试了以下两种场景:

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;

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

加载页面';通过代码收集的控件

我遇到了完全相同的要求,即需要在运行时从页面B评估页面a的控件。

在页面的整个生命周期中运行页面还需要一个额外的步骤。我们只需要调用Page.ProcessRequest()方法。Page.ProcessRequest方法(MSDN)。该方法对Intellisense隐藏。

在此之后,您将能够访问页面中的控件:

Page page = (Page)BuildManager.CreateInstanceFromVirtualPath("~/MyPage.aspx", typeof(Page));
page.ProcessRequest(HttpContext.Current);

如果你的页面有一个母版页,你需要深入了解母版页的占位符。

不过,一定要注意微软的评论:

"你不应该调用这个方法。"

"此API支持.NET Framework基础结构,并且不打算直接从代码中使用。"

我还不知道这样做是否会产生任何不利影响。


EDIT:在一个页面中执行一个页面可能会导致无数问题,所以我的方向略有不同。

使用HTML敏捷包,我们可以很容易地加载*.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;
}

我不会打乱页面生命周期。让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);
        }
    }
}

您过于复杂了;只需在Page.Controls集合中递归循环并检查您感兴趣的控件类型。看看前面的问题:

ASP.Net/C#,循环浏览页面上的某些控件?

循环浏览asp.net网页上的所有控件