动态加载的 UserControl 加载 DropDownList 项目一旦在 PostBack 上消失

Dynamically Loaded UserControl Loading DropDownList Items Once Disappear on PostBack

技术:Asp.Net4.5

我有一个项目可能会加载数百个不同的动态用户控件。当然一次一个,这取决于用户的选择。用户控件界面将在加载时从数据库中填充。

当使用下拉列表动态加载用户控件时,我只想加载一次项目。但是,这些项目在回发时消失了。我在用户控件中使用 Page_Load 来填充下拉列表。我也尝试过 OnInit。到目前为止我尝试过的任何东西似乎都不起作用。

奇怪的是,如果我从主页调用 usercontrol 中的方法,那么每次回发时项目都会保留,而不必每次都重新填充项目。

我希望在添加用户控件时加载一次项目。这是示例代码(非常简单)

主页 - Aspx

<%@ Page Language="vb" AutoEventWireup="false"   CodeBehind="WebForm5.aspx.vb" Inherits="WebApplication1.WebForm5" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
<form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Load User Control" />
        <asp:Button ID="Button2" runat="server" Text="PostBack" />
        <asp:Button ID="Button3" runat="server" Text="Invoke Method" />
        <asp:Panel ID="Panel1" runat="server">
        </asp:Panel>
    </div>
</form>
</body>
</html>

主页 - 代码隐藏

Public Class WebForm5
Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Request.Form(Button1.UniqueID) IsNot Nothing Then
        Session("IsLoading") = True
        Panel1.Controls.Clear()
    End If

    If IsPostBack = True Then
        Dim MyControl As UserControl = Page.LoadControl("UserControls\UcTest.ascx")
        MyControl.ID = "UcTest"
        MyControl.EnableViewState = True
        Panel1.Controls.Add(MyControl)
    End If

End Sub

Protected Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click

    Dim uc As UserControl = Panel1.FindControl("UcTest")
    If uc IsNot Nothing Then
        Dim s As String = ""
        Dim method As System.Reflection.MethodInfo = uc.GetType.GetMethod("LoadItems")
        If method IsNot Nothing Then
            method.Invoke(uc, New Object() {s})
        End If
    End If

End Sub

End Class

EDIT - 这根据 Ann 的回答解决了问题。使用 PreInit 而不是 Page_Load

  Private Sub WebForm5_PreInit(sender As Object, e As EventArgs) Handles Me.PreInit
    If Request.Form(Button1.UniqueID) IsNot Nothing Then
        Session("IsLoading") = True
        Panel1.Controls.Clear()
    End If

    If IsPostBack = True Then
        Panel1.Controls.Clear()
        Dim MyControl As UserControl = Page.LoadControl("UserControls\UcTest.ascx")
        MyControl.ID = "UcTest"
        MyControl.EnableViewState = False
        Panel1.Controls.Add(MyControl)
        MyControl.EnableViewState = True
    End If

End Sub

用户控件 - Aspx

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="UcTest.ascx.vb" Inherits="WebApplication1.UcTest" %>

<br />
<asp:DropDownList ID="DropDownList1" runat="server" Width="150" AutoPostBack="false" EnableViewState="True">
</asp:DropDownList>

用户控件 - 代码隐藏

Public Class UcTest
Inherits System.Web.UI.UserControl

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Session("IsLoading") = True Then

        'To be populated from database in the real app
        'Simplified here for testing

        DropDownList1.Items.Add("Red")
        DropDownList1.Items.Add("Green")
        DropDownList1.Items.Add("Blue")
        Session("IsLoading") = False
    End If

End Sub

Public Sub LoadItems(s As String)
    DropDownList1.Items.Add("Red")
    DropDownList1.Items.Add("Green")
    DropDownList1.Items.Add("Blue")
End Sub

End Class

根据 Microsoft 的 documentation,如果您想要恢复它们的值,您动态添加的控件将需要在 ViewState 加载时存在。从 ViewState 加载发生在 InitializationLoad 阶段之间。

Microsoft 建议在 PreInit 中重新创建它们: