如何不将元素集中在应用程序启动上?

How to not focus element on application startup?

最简单的应用可能:

<Page
    x:Class="TestApp.MainPage"
    ...>
    <Grid>
        <TextBox />
    </Grid>
</Page>

问题:有什么优雅的方法可以防止在应用程序启动时在文本框中设置光标(焦点)?

扩展:我真正的问题是我有一个 PopUp,它在 TextBox 获得焦点时打开。如果我单击 PopUp 中的一个元素,它应该关闭,但由于 TextBox 是我页面中的第一个可聚焦元素,它会自动获得焦点,因此 PopUp 会立即再次打开。我认为问题的核心就是上面的例子。

焦点由 IsTabStopTabIndexIsHitTestVisibleFocusManager class 等各种属性管理。一旦 window 被激活,内置功能会聚焦第一个可聚焦元素,并且此行为通常不可自定义。

我们可以指定另一个要聚焦的元素而不是文本框,例如页面本身:

<Page IsTabStop="True">
    <TextBox/>
</Page>

这是因为页面获得了初始焦点而不是文本框,但现在页面参与了跳格行为,这有点不受欢迎。

通常情况下,当您单击焦点控件外时,框架会将焦点设置到 RootScrollViewer,即使 RootScrollViewer 不是制表位(因此它无法通过 Tab 键获得焦点)。如果我们可以在页面加载时聚焦 RootScrollViewer,框架将检测到某物具有焦点并且不会尝试聚焦第一个元素。

<Page Loaded="onPageLoaded">
    <TextBox/>
</Page>
private ScrollViewer getRootScrollViewer()
{
    DependencyObject el = this;
    while (el != null && !(el is ScrollViewer))
    {
        el = VisualTreeHelper.GetParent(el);
    }

    return (ScrollViewer)el;
}

private void onPageLoaded(object sender, RoutedEventArgs e)
{
    getRootScrollViewer().Focus(FocusState.Programmatic);
}

这是我所知道的防止文本框自动聚焦的最"elegant"方法。