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.
精彩评论