【问题标题】:How to set focus back to control that originated postback如何将焦点重新设置为控制发起的回发
【发布时间】:2016-04-05 14:37:10
【问题描述】:

为避免无根据的“重复”标记,让我先说一下 - 我已经搜索了很多答案,但只找到了像 this 这样没有答案的答案,或者 this 告诉我使用 @ 987654323@ 来自我后面的代码。这样做正常工作。我会解释的。

我在更新面板中有一系列下拉控件,每个下拉控件都会影响之后的控件 - 城市、建筑物和房间。当用户在城市下拉菜单、鼠标或键盘中更改选择时,焦点会立即丢失,因为页面会执行部分回发。好的,所以我尝试输入CityListDropDown.Focus();,但这会导致页面重新定位自身,以便此控件位于页面可见区域的底部 - 而不是所需的行为。页面根本不应该移动。请注意,这仅在更新面板之前的页面上有很多其他内容时才重要,因此这些提示位于页面必须向下滚动到它们的下方。

那么,如何将焦点恢复到该城市下拉菜单,以便当用户使用键盘时,他们可以继续运送到下一个提示?建筑物下拉也是如此。

这是我的html:

            <asp:UpdatePanel ID="RoomsUpdatePanel" runat="server" UpdateMode="Conditional" RenderMode="Inline">
                <ContentTemplate>
                                <asp:DropDownList ID="CityListDropDown" runat="server" class="form-control input-sm" Width="140" AutoPostBack="True" OnSelectedIndexChanged="CityListDropDown_SelectedIndexChanged">
                                </asp:DropDownList>
                                <asp:DropDownList ID="BuildingListDropDown" runat="server" class="form-control input-sm" AutoPostBack="True" Width="100" OnSelectedIndexChanged="BuildingListDropDown_SelectedIndexChanged">
                                </asp:DropDownList>
                                <asp:DropDownList ID="RoomListDropDown" runat="server" class="form-control input-sm" AutoPostBack="False" Width="175">
                                </asp:DropDownList>
                </ContentTemplate>
            </asp:UpdatePanel>

这是我的代码:

    protected void CityListDropDown_SelectedIndexChanged(object sender, EventArgs e)
    {
        LoadBuildingList();
        LoadRoomList();
        CityListDropDown.Focus();
    }

    protected void BuildingListDropDown_SelectedIndexChanged(object sender, EventArgs e)
    {
        LoadRoomList();
        BuildingListDropDown.Focus();
    }

【问题讨论】:

    标签: asp.net focus postback


    【解决方案1】:

    如果您不希望页面在焦点更改时滚动/重新定位,您可以使用 Page 指令的 PageMaintainScrollPositionOnPostback 属性:

    <%@ PageMaintainScrollPositionOnPostback="true" ... %>
    

    或者您可以尝试通过代码以编程方式设置它:

    Page.MaintainScrollPositionOnPostBack = true;
    

    【讨论】:

    • 知道什么控件触发了回发不是问题。而且,正如我在问题中解释的那样,使用控件的 Focus() 方法无法正常工作。它重新定位整个页面。如果在回发发生时您在页面的中途滚动,则整个页面将重新定位,使其处于可能的最高位置,同时仍显示该控件。当用户在其中一个控件中选择一个选项时,页面不应“跳转”。
    • 我已经更新了我的回复。您可以尝试使用提到的属性 (PageMaintainScrollPositionOnPostback) 来查看这是否有助于解决问题并防止您的页面“跳跃”。
    • 我在我发现的一个问题中看到了这一点,但他们声称它不起作用。我刚刚尝试过,果然它不起作用,我的页面仍然被重新定位。我认为 Focus() 方法只是简单地覆盖任何试图保持页面位置并告诉页面重新定位以使控件具有焦点的任何内容。顺便说一句,Page和MaintainScrollPositionOnPostback之间应该有一个空格。
    • 如果您删除Focus() 调用以及使用PageMaintains.. 属性,这似乎有效吗?假设因为触发事件的控件在触发时应该有焦点(从而保持它们的位置)。
    • 否 - 部分回发总是导致控件失去焦点。只是试图确保,并按我的想法工作 - 失去焦点。
    【解决方案2】:

    我明白了!因此,使用控件的 Focus() 方法后面的代码会导致页面自行重新定位,即使您已将页面的 MaintainScrollPositionOnPostBack 属性设置为 true。但是,javascript 可以改变焦点,而无需不必要地移动页面。因此,如果我需要将焦点从后面的代码重置到发送控件,我可以这样做:

        protected void CityListDropDown_SelectedIndexChanged(object sender, EventArgs e)
        {
            LoadBuildingList();
            LoadRoomList();
            ScriptManager.RegisterStartupScript(CityListDropDown, CityListDropDown.GetType(), "CityDropDownRefocus", "document.getElementById(\"" + CityListDropDown.ClientID + "\").focus();", true);
        }
    

    或者,如果我希望重置焦点的那行代码更通用(假设我有一个由多个控件使用的事件处理程序,并且我需要处理程序将焦点重置到生成回发的控件,处理程序将获取发送对象,所以我可以说:

    protected void MyControlHandler(object sender, EventArgs e)
    {
        ...
        ScriptManager.RegisterStartupScript((WebControl)sender, sender.GetType(), "CityDropDownRefocus", "document.getElementById(\"" + ((WebControl)sender).ClientID + "\").focus();", true);
    }
    

    这会将焦点重置回发送控件,而无需移动页面!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 2012-10-05
      相关资源
      最近更新 更多