В UWP GetRectFromCharacterIndex не возвращает значения, откорректированные в соответствии со стилем элемента управления. - PullRequest
0 голосов
/ 12 мая 2018

При использовании GetRectFromCharacterIndex в UWP (в отличие от WPF) результатом является абсолютное смещение от места ввода текста, а не внутри элемента управления.

Например, следующий XAML:

<TextBox x:Name="noPadding" Margin="0,0,0,20" Text="aaa"/>

При вызове GetRectFromCharacterIndex(0) возвращает различное значение Rect.Left для UWP и WPF.

WPF: Rect.Left == 3 UWP: Rect.Left == 0

Разница становитсяЕще более отчетливо, когда вы изменяете стиль или иначе вид элемента управления:

<TextBox x:Name="withPadding" Padding="60,0,0,0" Margin="0,0,0,20" Text="aaa"/>

WPF: Rect.Left == 63 UWP: Rect.Left == 0

Как мне узнать фактическое местоположение персонажа наэлемент управления?

Примечание: Я знаю, что могу взломать его, вычислив позицию из TextView, который находится внутри TextBox.Но я пытаюсь понять, что поддерживает способ сделать это.

1 Ответ

0 голосов
/ 20 мая 2018

Итак, учитывая, что это еще не поддерживается должным образом, вот как я обошел его (если кто-то найдет «поддерживаемое» решение, я сниму отметку с моего ответа и отметлю его)

Этот метод расширения, кажется, подходитхитрость:

    public static Rect GetRelativeRectFromCharacterIndex(this TextBox textBox, int charIndex, bool trailingEdge)
    {
        var caret = textBox.GetRectFromCharacterIndex(charIndex, trailingEdge);

        // Hack: UWP does not properly return the location compared to the control, so we need to calculate it.
        // /10830487/getrectfromcharacterindex-vozvraschaet-znacheniya-otkorrektirovannye-sootvetstvii-stilem-elementa-upravleniya
        var scroller = textBox.GetDescendants().OfType<ScrollContentPresenter>().FirstOrDefault();
        var transform = scroller.TransformToVisual(textBox);
        transform.TryTransform(new Point(caret.Left, caret.Top), out var topLeft);
        transform.TryTransform(new Point(caret.Right, caret.Bottom), out var bottomRight);

        caret = new Rect(topLeft, bottomRight);
        return caret;
    }

Затем вам нужно GetDescendants ():

    public static IEnumerable<DependencyObject> GetDescendants(this DependencyObject container)
    {
        var stack = new Stack<DependencyObject>();
        stack.Push(container);

        while (stack.Count > 0)
        {
            var item = stack.Pop();
            var count = VisualTreeHelper.GetChildrenCount(item);
            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(item, i);
                yield return child;
                stack.Push(child);
            }
        }
    }
...