0

我熟悉在页面的第一次加载和随后的回发中创建和持久化动态控件,但是我在以下用户启动的场景中遇到了麻烦......

在我的演示中,我有一个占位符、两个按钮和一个文字

<div>
    <asp:PlaceHolder ID="phResponses" runat="server" />
</div>
<div>
    <asp:Button ID="btnAdd" Text="Add" runat="server" OnClick="Add"/>
    <asp:Button ID="btnInspect" Text="Inspect" runat="server" OnClick="Inspect"/>
</div>
<div>
    <asp:Literal ID="litResult" runat="server"/>
</div>

我希望用户能够单击添加按钮以提供响应,所以我有...

protected void Page_Init(object sender, EventArgs e)
{
    BuildControls();
}

protected void Add(object sender, EventArgs e)
{
    BuildControls();
}

protected void BuildControls()
{
    phResponses.Controls.Add(new LiteralControl { ID = "response_" + _Count.ToString() });
    _Count++;
}

_Count 是一个静态成员变量,使我能够拥有新控件的唯一 ID。我意识到我需要重建 Page_Init 上的动态控件,但问题是每次回发时我都会得到 2 个新的 Literal 控件。此外,如果将任何 Text 属性放入新控件中,则在重建控件时它会丢失。

那么如何避免添加多个控件以及在重建这些控件时如何保留新添加的属性?

我使用以下内容检查响应

protected void Inspect(object sender, EventArgs e)
{
    foreach (var control in phResponses.Controls)
    {
        if (control is LiteralControl)
        {
            litResults.Text += "<p>" + control.Text + " : " + control.ID + "</p>";
        }
    }
}

由于 Page_Init 上的重建,它本身添加了另一个不需要的控件

4

1 回答 1

0

我不确定我是否完全理解你的要求,但看起来你只是想确保BuildControls每个生命周期只调用一次。您可以通过进行以下更改来做到这一点:

  1. 添加一个新的private bool _isControlsBuilt = false;.
  2. 更改为打电话前Page_Init检查。_isControlsBuiltBuildControls
  3. 设置_isControlsBuilttrue以内BuildControls
  4. 确保BuildControls页面生命周期中比Page_Init.

至于在回发时丢失控件的值,那就是它们永远不会达到视图状态。我不确定它是否有效,但我的第一个猜测是在BuildControlsto call的末尾添加一行Page.RegisterRequiresControlState

protected void BuildControls()
{
    LiteralControl newLiteral = new LiteralControl { ID = "response_" + _Count };
    this.RegisterRequiresControlState(newLiteral);
    phResponses.Controls.Add(newLiteral);

    _Count++;
    _isControlsBuilt = true;
}

如果这不起作用(这可能意味着它是 _view_state,而不是 _control_state 对您来说很重要),您可能需要查看滚动您自己的视图状态。我在对 #3854193 的回答中写了如何做到这一点,您可能会觉得这很有用。

于 2010-10-13T12:55:01.960 回答