开发者

Obtaining caret position in TextBox

开发者 https://www.devze.com 2022-12-14 11:37 出处:网络
How to get caret position (x, y) in the visible client zone in TextBox control? I need to add an 开发者_运维百科auto complete feature to the text box.

How to get caret position (x, y) in the visible client zone in TextBox control? I need to add an 开发者_运维百科auto complete feature to the text box.

I've found solution for WPF, but it can't be applied in Silverlight.


public class AutoCompleteTextBox : TextBox
{
    public Point GetPositionFromCharacterIndex(int index)
    {
        if (TextWrapping == TextWrapping.Wrap) throw new NotSupportedException();

        var text = Text.Substring(0, index);

        int lastNewLineIndex = text.LastIndexOf('\r');

        var leftText = lastNewLineIndex != -1 ? text.Substring(lastNewLineIndex + 1) : text;

        var block = new TextBlock
                        {
                            FontFamily = FontFamily,
                            FontSize = FontSize,
                            FontStretch = FontStretch,
                            FontStyle = FontStyle,
                            FontWeight = FontWeight
                        };

        block.Text = text;
        double y = block.ActualHeight;

        block.Text = leftText;
        double x = block.ActualWidth;

        var scrollViewer = GetTemplateChild("ContentElement") as ScrollViewer;

        var point = scrollViewer != null
                        ? new Point(x - scrollViewer.HorizontalOffset, y - scrollViewer.VerticalOffset)
                        : new Point(x, y);
        point.X += BorderThickness.Left + Padding.Left;
        point.Y += BorderThickness.Top + Padding.Top;

        return point;
    }
}


In addition to altso's answer, I'd like to mention that you actually need to call .Measure() and .Arrange() methods on the block for .ActualHeight and .ActualWidth to work, for example, like this (parameters may vary depending on your use case):

 block.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
 block.Arrange(new Rect(0, 0, block.DesiredSize.Width, block.DesiredSize.Height));
 double y = block.ActualHeight;

This is required in WPF, and advised in Silverlight (including SL5). Otherwise you'll end up having 0 in ActualHeight in WPF and weird numbers in Silverlight (in my case, these were coordinates of a bounding box around all text).


As a separate solution, you could use FormattedText class to do the same trick.

0

精彩评论

暂无评论...
验证码 换一张
取 消