UWP中GetRectFromCharacterIndex未适配控件样式,如何获取字符实际位置?
获取UWP TextBox中字符在控件上的实际位置
确实,UWP里TextBox.GetRectFromCharacterIndex的行为和WPF差异很大——它返回的是文本输入可编辑区域的绝对偏移,而非相对于TextBox控件本身的坐标,这在自定义控件样式或调整Padding后会特别明显。
要获取字符在控件上的实际位置,官方推荐的标准方式是利用UIElement.TransformToVisual方法,结合TextBox公开的ContentHost属性来完成坐标系转换,完全不需要依赖内部未公开的TextView(这才是官方支持的实现)。
具体实现代码
假设你有一个名为withPadding的TextBox,代码如下:
// 获取字符在文本输入区域内的Rect var charInputRect = withPadding.GetRectFromCharacterIndex(0); // 获取TextBox的文本内容宿主(公开属性,官方支持) var contentHost = withPadding.ContentHost as FrameworkElement; if (contentHost != null) { // 将文本区域内的点转换为相对于TextBox控件的坐标 var charTopLeftInInputArea = new Point(charInputRect.Left, charInputRect.Top); var charTopLeftInTextBox = contentHost.TransformToVisual(withPadding) .TransformPoint(charTopLeftInInputArea); // 构建最终的、相对于TextBox的字符Rect var actualCharRect = new Rect( charTopLeftInTextBox.X, charTopLeftInTextBox.Y, charInputRect.Width, charInputRect.Height ); // 此时actualCharRect.Left就是你需要的控件内实际位置 }
原理说明
ContentHost是Control类的公开属性,指向TextBox中承载可编辑文本的内部容器(UWP里是TextBoxView,但我们不需要直接依赖这个具体类型),它的布局位置会自动响应TextBox的Padding、样式等设置。TransformToVisual是UIElement的核心API,专门用于在不同UI元素的坐标系之间转换坐标点,这是UWP官方提供的标准坐标转换方式,完全符合官方规范。
验证你的场景
针对你给出的带Padding="60,0,0,0"的TextBox:
- 调用
GetRectFromCharacterIndex(0)会得到相对于ContentHost的Left值(可能是0或默认内边距数值,取决于TextBox基础样式) - 经过转换后,
actualCharRect.Left会自动包含TextBox的Padding值(60)加上ContentHost自身的内边距,最终结果和WPF的行为对齐,得到字符在控件内的真实位置。
如果TextBox存在滚动(文本超出显示区域),可以给GetRectFromCharacterIndex传入第二个参数true来获取可见区域的坐标,转换逻辑依然适用。
内容的提问来源于stack exchange,提问作者Shahar Prish
相关产品推荐
相关产品推荐

