UWP TextBox - 专注于选择

UWP TextBox - Focus on selection

我有一个包含大量文本的 .NET UWP TextBox,我想在其中搜索一个词。当我点击按钮开始搜索时,它会找到这个词的第一次出现。当我再次点击时,它会找到第二个,就像记事本中的 ctrl+f)。

我想专注于找到的世界,但是当文本足够长以致于其中有滚动条时,它不会将找到的单词显示在视图中。

这是此状态下的屏幕截图,展示了我必须如何调整 window 的大小才能看到找到的单词。

这是我的搜索代码(textarea 是 TextBox 类型):

private void Find(string text)
    {
        textarea.Focus(FocusState.Programmatic);
        var start = textarea.SelectionStart + textarea.SelectionLength;
        var found =  (bool)checkboxFindCaseSensitive.IsChecked ? textarea.Text.IndexOf(text, start) : textarea.Text.IndexOf(text, start, StringComparison.CurrentCultureIgnoreCase);
        if (found == -1)
        {
            textarea.SelectionStart = 0;
            found = (bool)checkboxFindCaseSensitive.IsChecked ? textarea.Text.IndexOf(text, start) : textarea.Text.IndexOf(text, start, StringComparison.CurrentCultureIgnoreCase);
            if (found == -1) return;
        }
        textarea.SelectionStart = found;
        textarea.SelectionLength = text.Length;
    }

我已经尝试将 textarea.Focus(FocusState.Programmatic);textarea.Focus(FocusState.Pointer); 放在方法的末尾,但都没有帮助。

更新:

我发现它对焦正确,但是对焦到最后找到的单词(定位,找到下一个单词之前光标在哪里),而不是当前找到的单词。

所以我需要将焦点更新到当前 SelectionStart,而不是最后一个。有任何想法吗?我已经尝试再次更改 SelectionStart,替换文本并更新布局 - 没有任何帮助。

您可以测量文本的高度直到索引,然后相应地调整文本框的大小。

private static float GetTextHeightUntilIndex(TextBox textBox, int index)
    {
        var height = 0;
        var textBuffer = textBox.Text;

        // Remove everything after `index` in order to measure its size
        textBox.Text = textBuffer.Substring(0, index);
        textBox.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
        var height = textBox.DesiredSize().Height;

        // Put the full text back
        textBox.Text = textBuffer;

        return height;
    }

private void Find(string text)
    {
        textarea.Focus(FocusState.Programmatic);
        var start = textarea.SelectionStart + textarea.SelectionLength;
        var found =  (bool)checkboxFindCaseSensitive.IsChecked ? textarea.Text.IndexOf(text, start) : textarea.Text.IndexOf(text, start, StringComparison.CurrentCultureIgnoreCase);
        if (found == -1)
        {
            textarea.SelectionStart = 0;
            found = (bool)checkboxFindCaseSensitive.IsChecked ? textarea.Text.IndexOf(text, start) : textarea.Text.IndexOf(text, start, StringComparison.CurrentCultureIgnoreCase);
            if (found == -1) return;
        }
        textarea.SelectionStart = found;
        textarea.SelectionLength = text.Length;

        // -------------------

        var cursorPosInPx = GetTextHeightUntilIndex(textarea, found);

        // First method: resize your textbox to the selected word
        textarea.Height = cursorPosInPx; 

        // Second method: scroll the textbox
        var grid = (Grid)VisualTreeHelper.GetChild(textarea, 0);
        for (var i = 0; i <= VisualTreeHelper.GetChildrenCount(grid) - 1; i++)
        {
            object obj = VisualTreeHelper.GetChild(grid, i);
            if (obj is ScrollViewer)
                ((ScrollViewer)obj).ChangeView(null, cursorPosInPx, null, true);
        }
    }

但是请注意,对于第一种方法,根据文本框的布局,调整控件的大小可能会产生不需要的效果或根本没有效果。