在父页面更新面板占位符中动态加载新的用户控件

问题描述

预先感谢您的帮助。做这行已经很久了,我的记忆力不是最好的,但我知道这是可以做到的。

我有一个页面要求永远不要离开页面(没有回发)这就是为什么我使用 AJAX 和更新面板,并且基本上是流菜单。我去创建了多个用户控件,以便在页面上单独加载。

在父页面上,我放置了更新面板和占位符。

<asp:UpdatePanel ID="UpdatePanelContent" runat="server">
   <ContentTemplate>
      <asp:PlaceHolder ID="OaaSPlaceholder" runat="server">
      <!-- section loading area -->
      </asp:PlaceHolder>
   </ContentTemplate>
 </asp:UpdatePanel>

在父页面“OaaS”中,我能够成功加载 OaaSPlaceholder“tier_2_start.ascx”中的第一个控件,这可能是因为它是在 Page_Load 上从 OaaS 父页面本身调用的。问题是在尝试访问 OaaS 使用的相同方法时加载后续控件。方向性是控件调用 OaaS 主页公共方法来加载控件。按钮控件位于 UserControl 本身上,每个加载的 UserControl 都知道接下来要加载哪个控件。父页面对正在换入和换出的控件的感知为 0,这就是预期的操作。我说的是总共 2 打控件。

问题是访问父 OaaS 页面公共方法“LoadControl”以从按钮所在的 UserControl 加载下一个控件。我看到的行为是此解决方案当前加载前 2 个控件,但在调用第 3 个控件时加载第一个控件。所以少了点什么。

我在 OaaS 页面中创建了一个公共方法

public void LoadUserControl(string controlName)
{
    OaaSPlaceholder.Controls.Clear();
    UserControl uc = (UserControl)LoadControl(controlName);
    OaaSPlaceholder.Controls.Add(uc);

}

public void ClearControl()
{
    OaaSPlaceholder.Controls.Clear();
}

在每个用户控件(子控件)中,我想调用这个方法来加载下一个用户控件。在父级 (OaaS) 的 Page_Load 下方,效果很好。

 switch (tier)
 {
     case "tier1" :
         FULL_PATH = BASE_PATH + "Tier1/";
         break;
     case "tier2" :
         FULL_PATH = BASE_PATH + "Tier2/";
         controlPath = FULL_PATH + "tier_2_start.ascx";
         break;
     case "tier3" :
         FULL_PATH = BASE_PATH + "Tier3/";
         break;
     case "tier4" :
         FULL_PATH = BASE_PATH + "Tier4/";
         break;
     default:
         FULL_PATH = BASE_PATH + "Tier1/";
         break;
 }
 
 ClearControl();
 LoadUserControl(controlPath);

页面加载第一个 UserControl,是下一个有问题的控件,因为我试图从子控件访问父页面 OaaS 表单占位符。

tier_2_new.ascx 控件

protected void NextBtn_Click(object sender,EventArgs e)
{
    string action = ActionSelect.SelectedValue; // dropdown menu value from user selection
    string BASE_PATH = "~/OaaS_Controls/Tier2/";
    string controlPath = "";
    switch (action)
    {
        case "New":
            controlPath = BASE_PATH + action + "/tier_2_step_1.ascx"; // new control to be loaded
            ((OaaS)this.Page).ClearControl();
            ((OaaS)this.Page).LoadUserControl(controlPath);
            break;
        case "Decomission":
            // nothing yet
            break;
        case "Consultation":
            // nothing yet
            break;
    }
}

我收到 NullPointer 异常和所有类型的错误,当它的行为与预期不符时。那就是说我知道我做错了。任何帮助表示赞赏。

  System.NullReferenceException: 'Object reference not set to an instance of an object.'

“.Page”为空

NullPointer Error

Page Construction

解决方法

使用动态控件(UserControl 或其他)时,您需要跟踪当前有多少个控件,并在 PostBack 上添加新控件之前将它们全部添加,否则之前的控件将丢失。 所以这里有一个简单的例子。诀窍是将用户控件上的按钮单击委托给包含该用户控件的页面。

首先是包含用户控件的页面

<asp:UpdatePanel ID="UpdatePanelContent" runat="server">
   <ContentTemplate>

      <asp:PlaceHolder ID="OaaSPlaceholder" runat="server">    
      </asp:PlaceHolder>

   </ContentTemplate>
 </asp:UpdatePanel>

背后的代码

public partial class Default1 : System.Web.UI.Page
{
    //set the initial number of user controls
    int controlCount = 1;

    protected void Page_Load(object sender,EventArgs e)
    {
        //check if the viewstate with the controlcount already exists (= postback)
        if (ViewState["controlCount"] != null)
        {
            //convert the viewstate back to an integer
            controlCount = Convert.ToInt32(ViewState["controlCount"]);
        }
        else
        {
            //set the first viewstate
            ViewState["controlCount"] = controlCount;
        }

        //create the required number of user controls
        for (int i = 1; i <= controlCount; i++)
        {
            LoadUserControl("WebUserControl1.ascx",i);
        }
    }


    //add a new user control to the page
    public void LoadUserControl(string controlName,int index)
    {
        var uc = (WebUserControl1)LoadControl(controlName);
        uc.index = index;
        OaaSPlaceholder.Controls.Add(uc);

        uc.UserControlButton1 += new EventHandler(UC_Button1_Click);
    }


    //the delegated button click
    private void UC_Button1_Click(object sender,EventArgs e)
    {
        controlCount++;
        LoadUserControl("WebUserControl1.ascx",controlCount);
        ViewState["controlCount"] = controlCount;
    }
}

然后是用户控件

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="TestOmgeving.WebUserControl1" %>

<div style="border: 1px solid red; margin: 10px; padding: 10px;">

    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>

    <br />
    <br />

    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />

</div>

用户控制背后的代码

public partial class WebUserControl1 : System.Web.UI.UserControl
{
    public event EventHandler UserControlButton1;

    public int index { get; set; }

    protected void Page_Load(object sender,EventArgs e)
    {
        Label1.Text = "This is UserControl " + index;

        Button1.Text = "Load UserControl " + (index + 1);

        WebUserControl1 control = Page.Master.FindControl("UserControlOnMaster") as WebUserControl1;
    }


    //the button click from the user control
    protected void Button1_Click(object sender,EventArgs e)
    {
        Button1.Visible = false;

        OnUserControlButtonClick();
    }


    //the delegated control to the method of the parent page
    private void OnUserControlButtonClick()
    {
        if (UserControlButton1 != null)
        {
            UserControlButton1(this,EventArgs.Empty);
        }
    }
}