【问题标题】:PlaceHolders and Persistent Dynamic Controls (ADVANCED)占位符和持久动态控件(高级)
【发布时间】:2012-01-04 04:45:30
【问题描述】:

警告!这个问题不适合装腔作势。我花了几天时间尝试解决它。​​

我有一个Wizard 控件,大约有 5 个步骤,每个步骤都有几个控件,从非常简单到非常复杂,例如基于 DropDownLists 和 TextBoxes 的自定义 jQuery 组合框。每个步骤都有几个控件包裹在 PlaceHolder 控件中。

Wizard 以及所有 PlaceHolders 及其子 Controls 嵌套在 MultiViewView 内。在同一页面上,我还有另一个 View 样式类似于表单,但不是一个。此视图在Wizard 的每个步骤中为每个PlaceHolders 都有对应的PlaceHolders。

根据 ReferralUrl,我调用以下函数通过移动所有控件将视图从 Wizard“切换”到表单样式视图,然后按如下方式设置活动视图:

Protected Sub ToggleView() Handles ViewToggle.Click
    If Wizard_mv.ActiveViewIndex = 0 Then
        ViewToggle.Text = "Toggle Wizard View"
        fPH1.Controls.Add(wPH1)
        fPH2.Controls.Add(wPH2)
        fPH3.Controls.Add(wPH3)
        fPH4.Controls.Add(wPH4)
        fPH5.Controls.Add(wPH5)
        Wizard_mv.ActiveViewIndex = 1
    ElseIf Wizard_mv.ActiveViewIndex = 1 Then
        ViewToggle.Text = "Toggle Form View"
        wPH1.Controls.Add(fPH1)
        wPH2.Controls.Add(fPH2)
        wPH3.Controls.Add(fPH3)
        wPH4.Controls.Add(fPH4)
        wPH5.Controls.Add(fPH5)
        Wizard_mv.ActiveViewIndex = 0
    End If
End Sub

紧接着,我使用另一个函数来使用数据库中记录中的值预填充控件。在允许用户进行一些更改后,他们可以将更新的记录重新提交到数据库。问题是,如果我从Wizard 这样做,但在切换之后就不行了。跟踪显示Control Tree 在提交更新记录时为空,因此我无法从此视图中获取用户输入/预填充的值。 预填充效果很好,“选定”值都正确。单击提交后,PostBack 出现问题,它丢失了所有值和控件。

请不要回答,除非您完全理解我的问题并愿意提供帮助。我认为问题很好地存在于页面生命周期中。奇怪的是,当我从我的向导提交时,在 Page_Init 的回发中我加载了我的控件值,但是当我从我的表单视图提交时,既没有加载控件也没有加载它们的值。根据我的阅读,这是一个持久性问题。真的希望有一个相对简单的解决方案。

这是我在Wizard 中的标记示例(为简洁起见,删除了所有样式):

<asp:WizardStep ID="WizardStep1" runat="server" Title="Product Info">
    <asp:PlaceHolder ID="wPH1" runat="server" ViewStateMode="Enabled">
        <asp:Table ID="ProductInfoTable" runat="server" Width="100%">
            <asp:TableHeaderRow>
                <asp:TableHeaderCell><h3>Product Line</h3></asp:TableHeaderCell>
                <asp:TableHeaderCell><h3>Publication Type</h3></asp:TableHeaderCell>
                <asp:TableHeaderCell><h3>Request Type</h3></asp:TableHeaderCell>
            </asp:TableHeaderRow>
            <asp:TableRow>
                <asp:TableCell>
                    <div class="ui-widget">
                        <!-- Autocomplete Combobox -->
                        <asp:DropDownList ID="productLine_ddl" runat="server" DataSourceID="productLineSDS" ViewStateMode="Enabled" DataTextField="Product" DataValueField="ID"></asp:DropDownList>
                        <asp:TextBox ID="productLine_cb" runat="server" EnableViewState="True"></asp:TextBox>
                        <button id="productLine_btn" type="button" title="Show All Items"></button>
                    </div>
                </asp:TableCell>
                <asp:TableCell>
                    <asp:DropDownList ID="docType_ddl" runat="server" DataSourceID="docTypeSDS" DataTextField="DocType" DataValueField="ID"></asp:DropDownList>
                </asp:TableCell>
                <asp:TableCell>
                    <asp:DropDownList ID="requestType_ddl" runat="server" DataSourceID="requestTypeSDS" DataTextField="RequestType" DataValueField="ID"></asp:DropDownList>
                </asp:TableCell>
            </asp:TableRow>
            <asp:TableRow>
                <asp:TableCell ColumnSpan="2">
                    <asp:MultiView ID="Attachment_mv" runat="server" ActiveViewIndex="0">
                        <!-- File Upload/Browsing Display -->
                        <asp:View ID="AttachmentUploadView" runat="server">
                            <h3 class="inlineH">Attach File: </h3>
                            <asp:FileUpload ID="AttachmentFile_btn" runat="server" />
                            <asp:Button ID="UploadFile_btn" runat="server" Text="Upload File" />
                        </asp:View>
                        <!-- File Attached Display -->
                        <asp:View ID="FileAttachedView" runat="server">
                            <h3 class="inlineH">Uploaded File: </h3>
                            <asp:Label ID="FileAttachedLabel" runat="server" Text="Label"></asp:Label>
                            <asp:Literal ID="FilesOnServer" runat="server" />
                        </asp:View>
                    </asp:MultiView>
                </asp:TableCell>
            </asp:TableRow>
        </asp:Table>
    </asp:PlaceHolder>
</asp:WizardStep>

我的页面生命周期事件,根据要求(为了您的方便,按时间顺序排列):)

Dim referrerPage As String
'Initialize Dynamic controls here. These are controls that need to be prefilled, etc.
Private Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Init
    'DO NOT PREFILL at this stage, as the Controls are not yet rendered and will cause errors.
    '  Use this section for detecting the "referrerPage" and missing "id" parameters when expected, etc.
    If Not IsPostBack Then
        ViewState.Clear()
    End If

    Try
        referrerPage = Right(Request.UrlReferrer.AbsolutePath, Len(Request.UrlReferrer.AbsolutePath) - Request.UrlReferrer.AbsolutePath.LastIndexOf("/"c) - 1)
    Catch ex As Exception
        If Not String.IsNullOrEmpty(Session.Item("referrerPage")) Then
            referrerPage = Session.Item("referrerPage")
        End If
    End Try

    If StrComp(referrerPage, "wizard.aspx") <> 0 And String.IsNullOrEmpty(Session.Item("referrerPage")) Then 'Initialize Session state to remember "referrerPage"
        Session.Add("referrerPage", referrerPage)
    End If
    If StrComp(referrerPage, "formdetails.aspx") = 0 Then
        If String.IsNullOrEmpty(Request.Params("id")) Then
            'This line checks for an expected "id" param value and if none exists, forwards the page back to "tcom.aspx"
            Response.Redirect(Request.UrlReferrer.AbsolutePath)
        Else
            ToggleView()
        End If
    End If
End Sub

'Prefill Dynamic controls here.
Private Sub Page_PreLoad(sender As Object, e As EventArgs) Handles Me.PreLoad
    If Not IsPostBack Then
        productLine_ddl.DataBind()
        docType_ddl.DataBind()
        requestType_ddl.DataBind()
        '...and several more DataBinds for each individual
        '   control in the wizard. Nothing more.
    End If
End Sub

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
    If Not IsPostBack Then
        'Benign code for querying the database to get User info for Page.User.Identity.Name
    End If
End Sub

Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs) Handles Me.PreRender
    If Not IsPostBack Then
        'Here is completely benign code for hiding a couple controls.
    End If
End Sub

Protected Sub Page_PreRenderComplete(ByVal sender As Object, ByVal e As EventArgs) Handles Me.PreRenderComplete
    'PREFILL HERE when appropriate. This occurs after checking the "referrerPage" and ensuring a value for the "id" parameter.
    If Not IsPostBack Then
        Try
            If Not String.IsNullOrEmpty(Request.Params("id")) Then
                PrefillWizard(Request.Params("id"))
            Else : output.Text += "Source: " + Request.UrlReferrer.AbsolutePath
            End If
        Catch ex As Exception
        End Try
    End If
End Sub

对于任何可以提供帮助的人,我永远感激你。 ;)

【问题讨论】:

  • 您在页面生命周期的哪个部分生成控件?
  • @Felan:在Wizard 中,所有控件都在标记中静态声明,然后如果引用 url 正确,则移动到类似表单的视图。我在 Page_Init 中识别引用者、url 参数和 Toggle 视图,在 Page_PreLoad 中对控件进行 DataBind,并在 Page_PreRenderComplete 中预填充控件。 ;)
  • 正如您所说,您的生命周期事件可能是问题所在,您可以发布该代码吗?您是否有任何 if(!Postback) 代码?
  • @rickschott:按照要求,芽...并且对谁否决了这个问题大声笑。显然他们无法阅读,因为我已经对这个问题进行了大量研究,并付出了很多努力来询问它。 :P 我给出了公平的警告,这是一个大问题。干杯;)

标签: asp.net vb.net viewstate placeholder multiview


【解决方案1】:

问题是页面的控制树在每次回发期间必须完全相同。这意味着您必须每次都添加所有控件,无论设置了哪个ActiveViewIndex。最好在CreateChildControls 或页面初始化中。在ToggleView 函数中,您可以设置控件的可见性。

【讨论】:

  • 我终于找到了解决方案。我不确定你说的是否相同,所以让我问一下。我发现我的 ToggleView 在回发提交之前实际上并没有触发,所以实际上控件甚至没有加载,即ActiveViewIndex 不再正确。我的解决方案是添加一个 url 参数(也可以使用 Session 变量来完成)以在 Page_Init 期间检查先前的状态是否确实是我的基于表单的视图,如果是,则在进行更新之前重新切换它。这确保了首先填充控件。你说的是这个吗?
  • 并非如此。如果您在用户更改视图时动态添加控件。再次更改视图时,不会保留视图状态。始终在 CreateChildControls 中添加控件,而不是在视图更改时对其进行数据绑定/设置可见性。
  • 我会继续选择你的答案,但如果你不介意,如果你能在CreateChildControls 上多解释一下,我将不胜感激。这对我来说是一个新概念。谢谢;)
猜你喜欢
  • 1970-01-01
  • 2014-07-13
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 2013-06-24
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多