【问题标题】:ASP.NET web forms baffling postback behaviourASP.NET Web 表单令人费解的回发行为
【发布时间】:2017-01-17 15:13:54
【问题描述】:

我创建了一个小脚本来在异步回发期间保留焦点元素,并且在通过在 asp:Repeater 中生成的控件时,它工作得非常好除了,其中 完整的回发 出于某种神秘的原因被触发。这是一个简洁的示例:

<%@ 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>

此示例显示了工作和非工作行为。如果单击第一个文本框,更改值,tab 到下一个,更改值,tab 到下一个,它正确地将焦点保留在最后一个元素上,您可以在 JS 控制台中看到保留的焦点元素的进度。

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

这里发生了什么?这看起来一定是网络表单错误,否则我无法理解。如果是错误,是否有解决方法?

【问题讨论】:

    标签: javascript asp.net webforms


    【解决方案1】:

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

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

    <pages ClientIDMode="AutoID" / 
    

    在 web.config 中。

    【讨论】:

      【解决方案2】:

      它看起来不像是一个错误,但您的 JavaScript 函数在某种程度上是 PostBack 的原因。如果您将其完全删除,则 TextBox 会按应有的方式运行。脚本绑定的文本框(仅在页面首次加载时触发)与异步回发后在中继器内重新生成的文本框之间可能存在不匹配。

      如果您为 Async PostBack 注册所有文本框,它们将再次工作。

      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);
          }
      }
      

      【讨论】:

      • 当然它可以在没有脚本的情况下工作,这就是这个问题的重点。我没有在 JS 中绑定任何文本框,也没有做任何特别的事情。 page_Loading 事件在收到异步回复时触发,当前焦点元素的 id 被保存,然后 page_Loaded 事件触发(不是只是在您声称的第一次加载时),此时焦点恢复通过 id 查找元素并调用 focus()。我不缓存任何东西,我总是按 id 查找控件。这里没有什么特别的,这是一个简单得离谱的脚本。感谢您的解决方法,但这究竟是不是一个错误?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2020-10-30
      • 2018-07-02
      • 2020-06-19
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多