windows-8 - 当虚拟键盘打开时,以编程方式将控件滚动到 View 中

标签 windows-8 windows-runtime winrt-xaml

我有一个带有一组垂直文本框的页面。如果其中之一获得焦点,则即使显示屏幕键盘,所有这些都应该可见。它们的数量刚好足以容纳键盘上方的可用空间。当底部文本框获得焦点时,页面会自动向上滚动,以便所有文本框都可见,但如果顶部文本框获得焦点,屏幕键盘会覆盖底部文本框。

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

<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()
    };
}

我已经尝试了几种方法,但都没有成功:

  1. TextBox.GotFocus 事件中以编程方式将焦点更改为底部文本框并返回。
  2. TextBox.GotFocus 事件和 InputPane.Showing 事件中尝试设置 ScrollViewer 的垂直偏移:(a) 我包含的那个在 Grid 周围的页面中 (b) 视觉树中 Page 上方的一个,Windows 使用它自动将焦点控件带入 View 。在这两种情况下,ScrollViewer 不会对 ScrollToVerticalOffset 调用使用react。

我还查看了 sample this question中建议但它对屏幕键盘的 react 不同,而不是通过滚动页面。

最佳答案

感谢 Cyprient 的回答,我终于成功地让它发挥作用。我从问题中选择了选项 2.a。

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

  1. 我必须将代码放入 InputPaneShowing 事件中。
  2. 我必须将其放入调度程序的回调中,以便仅在 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;
}

关于windows-8 - 当虚拟键盘打开时,以编程方式将控件滚动到 View 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12638117/

相关文章:

c# - '<Module>' 的类型初始值设定项抛出异常并且算术运算导致溢出

xaml - Windows 应用商店应用日历 XAML 控件

visual-studio - 使用控件本身时,如何使用伪数据设计时初始化 XAML UserControl?

c# - 编译 C++ 源代码以在 Windows 应用商店应用程序 (Windows 8) 中使用它们

c# - 如何处理 Windows 8 XAML/C# 应用程序崩溃

c# - Windows 8 上列表框项目选择周围的白框

c# - 使用 ListView 的 WinRT ObservableCollection 删除操作

xaml - 我可以在 XAML 中定义变量吗?

wpf - 当今 WPF 中业务应用的发展趋势

c++ - 在 OnNavigatedTo 导航到另一个页面?