ASP.NET Web表单令人困惑的回发行为

时间:2017-01-17 15:13:55

标签: javascript asp.net webforms

我创建了一个小脚本来保留异步回发期间的焦点元素,并且在通过asp:Repeater内部生成的控件进行选项卡时,之外它完全正常,其中完整回发< / em>由于一些神秘的原因被触发。这是一个简明的样本:

<%@ Page Language="C#" EnableEventValidation="false" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <title></title>
    <script runat="server">
        public IEnumerable<int> Measurements_GetData()
        {
            return new[] { 123, 328, 1099 };
        }
    </script>
</head>
<body>
    <form method="post" runat="server">
        <asp:ScriptManager runat="server" />
        <asp:UpdatePanel runat="server">
            <ContentTemplate>
                <h1>OK</h1>
                <div>
                    <asp:TextBox ID="Measurement1" runat="server" Text="123" AutoPostBack="true"  />
                </div>

                <div>
                    <asp:TextBox ID="TextBox1" runat="server" Text="328" AutoPostBack="true" />
                </div>

                <div>
                    <asp:TextBox ID="TextBox2" runat="server" Text="1099" AutoPostBack="true" />
                </div>

                <h1>Not OK</h1>
                <asp:Repeater ID="Measurements" runat="server" SelectMethod="Measurements_GetData" ItemType="System.Int32">
                    <ItemTemplate>
                    <div>
                        <asp:TextBox ID="Measurement" runat="server" AutoPostBack="true" Text="<%# Item %>" />
                    </div>
                    </ItemTemplate>
                </asp:Repeater>
            </ContentTemplate>
        </asp:UpdatePanel>
    </form>
    <script type="text/javascript">
        (function () {
            var focusedElementId = "";
            var prm = Sys.WebForms.PageRequestManager.getInstance();

            prm.add_pageLoaded(function (source, args) {
                // re-focus element, if any selected prior to postback
                if (focusedElementId !== "") {
                    document.getElementById(focusedElementId).focus();
                    console.log("focus:" + focusedElementId);
                }
            });

            prm.add_pageLoading(function (source, args) {
                var fe = document.activeElement;
                focusedElementId = fe !== null ? fe.id : "";
            });
        })();
    </script>
</body>
</html>

此示例显示工作和非工作行为。如果单击第一个文本框,请将值,选项卡更改为下一个,将值更改为选项卡,然后将选项卡正确保留到最后一个元素,并且可以在JS控制台中查看保留的焦点元素的进度。

现在,如果您观看JS控制台并单击转发器生成的标记中的第一个文本输入(不正常部分),请更改然后选项卡,再次更改选项卡,您可以看到焦点在最后一个控件上丢失,因为完整触发回发(清除JS控制台)。

这里发生了什么?看起来它必须是一个Web表单错误,否则我无法理解它。如果是错误,是否有解决方法?

2 个答案:

答案 0 :(得分:1)

正如我所怀疑的,这是ASP.NET Web表单中的一个已知问题。它是由ASP.NET 4.0中的ClientIDMode更改引起的。 MS发布了some workarounds here

如果您不关心生成的控件ID,最简单的解决方案似乎是reverting to pre-ASP.NET 4.0 behaviour by setting

<pages ClientIDMode="AutoID" / 
web.config中的

答案 1 :(得分:0)

它看起来不像是一个bug,但是你的JavaScript函数在某种程度上是PostBack的原因。如果完全删除它,TextBoxes就会按照它们的行为进行操作。您的脚本绑定的TextBox之间可能不匹配(仅在首次加载页面时触发)和在异步回发后在Repeater内重新生成的TextBox.

如果您注册了Async PostBack的所有TextBox,它们将再次运行。

protected void Page_Load(object sender, EventArgs e)
{
    foreach (RepeaterItem item in Measurements.Items)
    {
        TextBox tb = item.FindControl("Measurement") as TextBox;
        ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(tb);
    }
}