I have a page with a vertical set of textboxes. If one of them is focused, all of them should be visible, even if the onscreen keyboard is displayed. There are just enough of them that all of them fit in the available space above the keyboard. When the bottom textbox is focused, the page gets automatically scrolled up so that all of them are visible, but if the top textbox is focused, the onscreen keyboard covers the bottom one.
This is a simplified example of my page:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ItemsControl ItemsSource="{Binding List}" Margin="120 140 0 0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0 10 0 0">
<TextBox Text="{Binding Text, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
DataContext
contains a list of 10 items:
public class Item
{
public string Text { get; set; }
}
public class ViewModel
{
public List<Item> List { get; set; }
}
public MainPage()
{
this.InitializeComponent();
DataContext = new ViewModel
{
List = Enumerable.Range(0, 10).Select(i => new Item { Text = i.ToString() }).ToList()
};
}
I've already tried a couple of approaches, all without success:
- In
TextBox.GotFocus
event programmatically changed focus to the bottom textbox and back. - In
TextBox.GotFocus
event andInputPane.Showing
event tried setting the vertical offset of aScrollViewer
: (a) the one I included in the page around theGrid
(b) the one in the visual tree above thePage
that Windows uses to automatically bring the focused control in view. In both cases theScrollViewer
doesn't react toScrollToVerticalOffset
calls.
I've also looked at the sample suggested in this question but it reacts to onscreen keyboard differently, not by scrolling the page.
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.
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 theGotFocus
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:Showing
event ofInputPane
.Showing
event handler had already returned.Here's the final code:
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: