我有一个带有一组垂直文本框的页面。如果其中一个聚焦,则即使显示屏幕键盘,它们也应该可见。它们的数量足够多,以至于它们都适合键盘上方的可用空间。当底部文本框聚焦时,页面会自动向上滚动,以便所有文本框都可见,但如果顶部文本框聚焦,屏幕键盘将覆盖底部文本框。
这是我页面的简化示例:
<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
包含 10 个项目的列表:
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()
};
}
我已经尝试了几种方法,但没有成功:
- 在
TextBox.GotFocus
事件中,以编程方式将焦点更改为底部文本框并返回。 - 在
TextBox.GotFocus
事件和InputPane.Showing
事件中尝试设置ScrollViewer
的垂直偏移量:(a) 我包含在Grid
周围页面中的那个 (b) Windows 用于自动显示焦点控件的Page
上方的可视化树中的那个。在这两种情况下,ScrollViewer
都不会对ScrollToVerticalOffset
调用做出反应。
我还查看了此问题中建议的示例,但它对屏幕键盘的反应不同,而不是通过滚动页面。
多亏了Cyprient的回答,我终于设法让它工作了。我从我的问题中追求选项 2.a。
需要添加UpdateLayout()
调用,但是当我将其放入GotFocus
事件处理程序中时,它仅在虚拟键盘已打开后才起作用。为了使它在键盘仍然打开时第一次工作,我必须进行两项更改:
- 我不得不将代码放在
InputPane
的Showing
事件中。 - 我必须将其放在调度程序的回调中,以便仅在
Showing
事件处理程序返回后才调用它。
这是最终代码:
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();
});
}
这是我用来获取对页面内容自动滚动时使用的相同ScrollViewer
的引用的帮助程序函数,因为否则不会显示焦点控件:
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;
}
有时,当您使用 ScrollToVerticalOffset 时,ScrollViewer 不会自行刷新。 解决方法包括调用滚动查看器。UpdateLayout() 在滚动后。它在几种情况下对我有用。