Windows 8 当虚拟键盘打开时,以编程方式将控件滚动到视图中

Windows 8 当虚拟键盘打开时,以编程方式将控件滚动到视图中,windows-8,windows-runtime,winrt-xaml,Windows 8,Windows Runtime,Winrt Xaml,我有一个垂直的文本框页面。如果其中一个已聚焦,则即使屏幕上显示了键盘,也应能看到所有的图像。它们的数量刚好足够,所有这些都可以放在键盘上方的可用空间中。当底部文本框聚焦时,页面会自动向上滚动,以便所有文本框都可见,但如果顶部文本框聚焦,屏幕键盘会覆盖底部文本框 这是我的页面的一个简化示例: <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <ItemsControl Item

我有一个垂直的文本框页面。如果其中一个已聚焦,则即使屏幕上显示了键盘,也应能看到所有的图像。它们的数量刚好足够,所有这些都可以放在键盘上方的可用空间中。当底部文本框聚焦时,页面会自动向上滚动,以便所有文本框都可见,但如果顶部文本框聚焦,屏幕键盘会覆盖底部文本框

这是我的页面的一个简化示例:

<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>
我已经尝试过几种方法,但都没有成功:

  • TextBox.GotFocus中,事件以编程方式将焦点更改为底部文本框并返回
  • TextBox.GotFocus
    事件和
    输入窗格中。显示
    事件尝试设置
    ScrollViewer
    的垂直偏移量:(a)我包含在
    网格周围的页面中的一个(b)Windows用于自动查看聚焦控件的
    页面上方视觉树中的一个。在这两种情况下,
    ScrollViewer
    不会对
    ScrollToVerticalOffset
    调用做出反应

  • 我也看过中建议的,但它对屏幕键盘的反应不同,不是通过滚动页面。

    有时当您使用ScrollToVerticalOffset时,ScrollViewer不会自动刷新。
    解决方法是在滚动后调用scrollviewer.UpdateLayout()。有好几种情况下它对我有效。

    多亏了Cyprient的回答,我终于成功地实现了这一点。我从我的问题中选择了选项2.a

    添加
    UpdateLayout()
    调用是必需的,但当我将其放入
    GotFocus
    事件处理程序时,它仅在虚拟键盘已经打开后才起作用。为了让它在键盘仍处于打开状态时第一次工作,我必须进行两项更改:

  • 我不得不将代码放在
    显示
    输入窗格事件的
  • 我必须将它放在调度程序的回调中,以便只有在
    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();
            });
    }
    

    很抱歉,我之前没有回复,但我最近一直忙于其他事情。虽然您的回答引导我朝着正确的方向前进,但我正在添加一个完整的解决方案,我已经在我的文章中更详细地描述了该解决方案。
    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();
            });
    }
    
    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;
    }