2012-04-04 52 views
0

我正在嘗試編寫一個方法,該方法將動態加載給定頁面的控件集合,以便可以遍歷它並創建駐留在頁面上的某些類型的控件的列表。這個想法是,對於從特定頁面類繼承的任何頁面,我想編譯一個包含特定屬性的可編輯字段列表。這一切都發生在這些頁面之外(在允許用戶管理這些其他頁面的不同頁面上)。通過代碼加載頁面控件集合

我都試過以下情形:

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

爲什麼你不能把你的字段放在用戶控件中並從頁面A和頁面B訪問?在完成請求生命週期之前,您應該無法實例化頁面的控件集合,這與實例化該頁面的實例並不相同 - 您可能會發現通過UserControls可以更輕鬆地對字段進行子類化(您可以使用Page.LoadControl在飛行中加載) – dash 2012-04-04 22:11:30

回答

0

我所遇到完全在運行時需要從頁面B評估頁面A的控件的相同要求。

在頁面的生命週期中運行頁面還需要一個額外的步驟。我們只需要調用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; 
} 
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); 
     } 
    } 
} 
+0

問題是,我坐在頁面B上,我只需要獲取Page A的控件集合的實例,以便可以看到它包含的字段。這就是爲什麼我可以在數據庫中存儲關於所述字段的信息,而不必保留另一個只定義了頁面上的字段的表(它已經在標記中是過度的)。 – 2012-04-04 21:34:30

+0

爲什麼您需要從頁面'B'訪問頁面'A'?爲什麼你不能從頁面'A'訪問頁面'A'? – 2012-04-04 21:35:52

+0

由於我需要管理一個字段列表,我的選項是a)使用「relections type」方法來獲取另一個頁面上的字段列表,我可以使用它加載到用戶選擇的下拉列表中或b)創建我們希望讓用戶管理的所有字段的數據庫中的表格。選項b不好,因爲當我們創建新頁面或修改現有頁面時,我們不僅需要向標記添加字段(按照常規Web開發),而且我們還需要將所述字段添加到數據庫,以便可以在頁面之外進行管理。這是創建一個規則引擎來確定是否需要字段。 – 2012-04-04 21:44:53

0

你過於複雜它;只是循環遞歸通過Page.Controls收集和檢查你感興趣的控制類型看看這些早期的問題:

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

Loop through all controls on asp.net webpage

+0

問題是我需要循環通過未加載的頁面上的控件。我在頁面B上。我需要Page A的控件集合。 – 2012-04-04 21:41:53

+0

加載並存儲您的值在Session中循環瀏覽頁面A中的值? – IrishChieftain 2012-04-04 21:46:07

+0

我無法保證頁面已經被加載。 – 2012-04-04 21:47:38