【问题标题】:Dynamically Loaded UserControl Loading DropDownList Items Once Disappear on PostBack动态加载的用户控件加载 DropDownList 项目一旦在 PostBack 上消失
【发布时间】:2026-01-03 20:15:02
【问题描述】:

技术:Asp.Net 4.5

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

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

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

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

MainPage - 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>

MainPage - 代码隐藏

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

【问题讨论】:

  • 那绝对不是c#。
  • 如果我没记错的话,这就是所谓的 Visual Basic
  • 自动标签建议吸引了我。无论哪种方式,都应该能够弄清楚。

标签: vb.net visual-studio webforms user-controls


【解决方案1】:

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

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

【讨论】:

  • 谢谢安,你是对的。我确实将代码移到了 PreInit,但忘记先从面板清除每次回发的控件。一旦我这样做了,它就会按预期工作,我会将替代代码添加到原始帖子中。
  • 没有这个网站我会哭的。