gpt4 book ai didi

wpf - 从 TextBlock 获取显示的文本

转载 作者:行者123 更新时间:2023-12-03 11:24:28 33 4
gpt4 key购买 nike

我有一个像这样定义的简单 TextBlock

<StackPanel>
<Border Width="106"
Height="25"
Margin="6"
BorderBrush="Black"
BorderThickness="1"
HorizontalAlignment="Left">
<TextBlock Name="myTextBlock"
TextTrimming="CharacterEllipsis"
Text="TextBlock: Displayed text"/>
</Border>
</StackPanel>

哪个输出像这样

alt text

这会让我“TextBlock:显示的文本”
string text = myTextBlock.Text;

但是有没有办法获得实际显示在屏幕上的文本?
意思是“文本块:显示...”

谢谢

最佳答案

您可以通过首先检索 Drawing 来做到这一点。表示 TextBlock 外观的对象在视觉树中,然后走那个寻找 GlyphRunDrawing项目 - 这些将包含屏幕上实际呈现的文本。这是一个非常粗略和准备好的实现:

private void button1_Click(object sender, RoutedEventArgs e)
{
Drawing textBlockDrawing = VisualTreeHelper.GetDrawing(myTextBlock);
var sb = new StringBuilder();
WalkDrawingForText(sb, textBlockDrawing);

Debug.WriteLine(sb.ToString());
}

private static void WalkDrawingForText(StringBuilder sb, Drawing d)
{
var glyphs = d as GlyphRunDrawing;
if (glyphs != null)
{
sb.Append(glyphs.GlyphRun.Characters.ToArray());
}
else
{
var g = d as DrawingGroup;
if (g != null)
{
foreach (Drawing child in g.Children)
{
WalkDrawingForText(sb, child);
}
}
}
}

这是我刚刚编写的一个小测试工具的直接摘录 - 第一种方法是一个按钮单击处理程序,只是为了便于实验。

它使用 VisualTreeHelper得到渲染 DrawingTextBlock - 这只在事物已经被顺便渲染的情况下才有效。然后是 WalkDrawingForText方法完成实际工作 - 它只是遍历 Drawing树寻找文本。

这不是非常聪明 - 它假设 GlyphRunDrawing对象按您想要的顺序出现。对于您的特定示例,它确实如此 - 我们得到一个 GlyphRunDrawing包含被截断的文本,然后是包含省略号的第二个文本。 (顺便说一句,它只是一个 unicode 字符 - 代码点 2026,如果这个编辑器让我粘贴 unicode 字符,它是“...”。它不是三个单独的句点。)

如果你想让它更健壮,你需要计算出所有这些 GlyphRunDrawing 的位置。对象,并对它们进行排序,以便按照它们出现的顺序处理它们,而不是仅仅希望 WPF 碰巧按该顺序生成它们。

更新添加:

这是位置感知示例的外观草图。虽然这有点狭隘 - 它假设从左到右阅读文本。对于国际化解决方案,您需要更复杂的东西。
private string GetTextFromVisual(Visual v)
{
Drawing textBlockDrawing = VisualTreeHelper.GetDrawing(v);
var glyphs = new List<PositionedGlyphs>();

WalkDrawingForGlyphRuns(glyphs, Transform.Identity, textBlockDrawing);

// Round vertical position, to provide some tolerance for rounding errors
// in position calculation. Not totally robust - would be better to
// identify lines, but that would complicate the example...
var glyphsOrderedByPosition = from glyph in glyphs
let roundedBaselineY = Math.Round(glyph.Position.Y, 1)
orderby roundedBaselineY ascending, glyph.Position.X ascending
select new string(glyph.Glyphs.GlyphRun.Characters.ToArray());

return string.Concat(glyphsOrderedByPosition);
}

[DebuggerDisplay("{Position}")]
public struct PositionedGlyphs
{
public PositionedGlyphs(Point position, GlyphRunDrawing grd)
{
this.Position = position;
this.Glyphs = grd;
}
public readonly Point Position;
public readonly GlyphRunDrawing Glyphs;
}

private static void WalkDrawingForGlyphRuns(List<PositionedGlyphs> glyphList, Transform tx, Drawing d)
{
var glyphs = d as GlyphRunDrawing;
if (glyphs != null)
{
var textOrigin = glyphs.GlyphRun.BaselineOrigin;
Point glyphPosition = tx.Transform(textOrigin);
glyphList.Add(new PositionedGlyphs(glyphPosition, glyphs));
}
else
{
var g = d as DrawingGroup;
if (g != null)
{
// Drawing groups are allowed to transform their children, so we need to
// keep a running accumulated transform for where we are in the tree.
Matrix current = tx.Value;
if (g.Transform != null)
{
// Note, Matrix is a struct, so this modifies our local copy without
// affecting the one in the 'tx' Transforms.
current.Append(g.Transform.Value);
}
var accumulatedTransform = new MatrixTransform(current);
foreach (Drawing child in g.Children)
{
WalkDrawingForGlyphRuns(glyphList, accumulatedTransform, child);
}
}
}
}

关于wpf - 从 TextBlock 获取显示的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4319031/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com