0

To avoid unwarranted "duplicate" flagging, let me say upfront - I have searched high and low for an answer and only found ones like this, which has no answer, or this, which tells me to use MyControl.Focus(); from my code behind. That does not work properly. I will explain.

I have a series of dropdown controls in an update panel, each of which affects the ones after it - City, Building and Room. When the user changes the selection in the city dropdown, mouse or keyboard, focus is immediately lost as the page does the partial postback. Ok, so I try to put in the CityListDropDown.Focus();, but that causes the page to reposition itself so that this control is at the bottom of the visible area of the page - not the desired behavior. The page should not move at all. Mind you, this only matters if you have a lot of other stuff on the page before your update panel, so that these prompts are lower down where the page has had to scroll down to them.

So, how do I restore focus back to that city drop down so when the user is using the keyboard, they can just keep on trucking to the next prompt? Same goes for the building drop down.

Here is my 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>

and here is my code behind:

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

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

2 Answers2

0

If you don't want the page to scroll / get repositioned whenever the focus is changed, you can use the PageMaintainScrollPositionOnPostback property of the Page directive :

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

or you can try setting it programatically through code :

Page.MaintainScrollPositionOnPostBack = true;
Rion Williams
  • 74,820
  • 37
  • 200
  • 327
  • Knowing what control triggered the postback is not the problem. And, as I explained in my question, using the Focus() method of the control does not work properly. It repositions the entire page. If you are scrolled partway through the page when that postback happens, the whole page gets repositioned so that it is at the highest position possible while still showing that control. The page should not "jump" when the user selects an option in one of these controls. –  Apr 05 '16 at 14:52
  • I've updated my response. You can try using the property mentioned (PageMaintainScrollPositionOnPostback) to see if that helps resolve the issue and keeps your page from "jumping" around. – Rion Williams Apr 05 '16 at 15:03
  • I had seen this in one of the questions I found, but they claimed it did not work. I have just tried it and sure enough it did not work, my page still gets repositioned. I think that Focus() method simply overrides anything like this that tries to keep the page position and tells the page to reposition itself so that the control has focus. And by the way, there should be a space between Page and MaintainScrollPositionOnPostback. –  Apr 05 '16 at 15:08
  • If you remove the `Focus()` call along with using the `PageMaintains..` property does that seem to work? Assuming since the Controls that are triggering the events should likely have focus when they are triggered (thus persisting their position). – Rion Williams Apr 05 '16 at 15:10
  • No - the partial postback always causes the controls to lose focus. Just tried to make sure, and works as i thought - lost focus. –  Apr 05 '16 at 15:12
0

I got it! So using the code behind Focus() method of the control causes the page to reposition itself, even when you have set the MaintainScrollPositionOnPostBack property of the page to true. But, javascript can change focus without moving the page around unnecessarily. So if I need to reset focus from my code behind, to the sending control, I can do this:

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

or, if I want that line of code that resets the focus to be more generic (say I have an event handler that is used by multiple controls, and I need the handler to reset focus to the control that generated the postback, the handler is going to get the sending object, so I can say:

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

And that resets the focus back to the sending control, without moving the page around!