Programmatically scroll controls into view when virtual keyboard opens

可紊 提交于 2019-12-01 00:49:58

Thanks to Cyprient's answer I finally managed to get this to work. I pursued option 2.a from my question.

Adding UpdateLayout() call was required, but when I put it in the GotFocus event handler it only worked after the virtual keyboard was already opened. To make it work the first time when the keyboard was still opening, I had to make two changes:

  1. I had to put the code in the Showing event of InputPane.
  2. I had to put it in a callback for the dispatcher so that it was called only after the Showing event handler had already returned.

Here's the final code:

public MainPage()
{
    this.InitializeComponent();
    DataContext = new ViewModel
    {
        List = Enumerable.Range(0, 10).Select(i => new Item { Text = i.ToString() }).ToList()
    };

    var inputPane = InputPane.GetForCurrentView();
    inputPane.Showing += InputPane_Showing;
}

private async void InputPane_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            var parentScrollViewer = FindParent<ScrollViewer>(this.pageRoot);
            parentScrollViewer.VerticalScrollMode = ScrollMode.Enabled;
            parentScrollViewer.ScrollToVerticalOffset(65);
            parentScrollViewer.UpdateLayout();
        });
}

Here's the helper function I'm using to get the reference to the same ScrollViewer which is used when the page contents gets scrolled automatically because the focused control would not be shown otherwise:

public static T FindParent<T>(FrameworkElement reference)
    where T : FrameworkElement
{
    FrameworkElement parent = reference;
    while (parent != null)
    {
        parent = parent.Parent as FrameworkElement;

        var rc = parent as T;
        if (rc != null)
        {
            return rc;
        }
    }

    return null;
}

Sometimes the ScrollViewer does not refresh itself when you are using ScrollToVerticalOffset. The workaround consists in calling scrollviewer.UpdateLayout() after scrolling. It worked for me in several cases.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!