在 UWP 下,GetRectFromCharacterIndex 不会 return 值调整为控件的样式
Under UWP, GetRectFromCharacterIndex does not return values adjusted to the style of the control
在 UWP(相对于 WPF)中使用 GetRectFromCharacterIndex
时,结果是相对于可以输入文本的位置的绝对偏移量,而不是在控件内部。
例如下面的XAML:
<TextBox x:Name="noPadding" Margin="0,0,0,20" Text="aaa"/>
当您调用 GetRectFromCharacterIndex(0)
时,returns UWP 和 WPF 上的不同 Rect.Left
值。
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
如何获取角色在控件上的实际位置?
注意:我知道我可以通过计算 TextBox 内的 TextView 的位置来破解它。但我试图了解支持的方法是什么。
因此鉴于尚未得到适当支持,以下是我的解决方法(如果有人找到 "supported" 解决方案,我将取消标记我的答案并标记那个)
这个扩展方法似乎可以解决问题:
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.
//
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);
}
}
}
在 UWP(相对于 WPF)中使用 GetRectFromCharacterIndex
时,结果是相对于可以输入文本的位置的绝对偏移量,而不是在控件内部。
例如下面的XAML:
<TextBox x:Name="noPadding" Margin="0,0,0,20" Text="aaa"/>
当您调用 GetRectFromCharacterIndex(0)
时,returns UWP 和 WPF 上的不同 Rect.Left
值。
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
如何获取角色在控件上的实际位置?
注意:我知道我可以通过计算 TextBox 内的 TextView 的位置来破解它。但我试图了解支持的方法是什么。
因此鉴于尚未得到适当支持,以下是我的解决方法(如果有人找到 "supported" 解决方案,我将取消标记我的答案并标记那个)
这个扩展方法似乎可以解决问题:
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.
//
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);
}
}
}