wpf - Get Displayed Text from TextBlock -
i have simple textblock defined this
<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>
which outputs this
this me "textblock: displayed text"
string text = mytextblock.text;
but there way text that's displayed on screen?
meaning "textblock: display..."
thanks
you can first retrieving drawing
object represents appearance of textblock
in visual tree, , walk looking glyphrundrawing
items - contain actual rendered text on screen. here's rough , ready implementation:
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 glyphrundrawing; if (glyphs != null) { sb.append(glyphs.glyphrun.characters.toarray()); } else { var g = d drawinggroup; if (g != null) { foreach (drawing child in g.children) { walkdrawingfortext(sb, child); } } } }
this direct excerpt little test harness wrote - first method's button click handler ease of experimentation.
it uses visualtreehelper
rendered drawing
textblock
- that'll work if thing has been rendered way. , walkdrawingfortext
method actual work - traverses drawing
tree looking text.
this isn't terribly smart - assumes glyphrundrawing
objects appear in order you'll want them. particular example - 1 glyphrundrawing
containing truncated text, followed second 1 containing ellipsis character. (and way, it's 1 unicode character - codepoint 2026, , if editor lets me paste in unicode characters, it's "…". it's not 3 separate periods.)
if wanted make more robust, need work out positions of glyphrundrawing
objects, , sort them, in order process them in order in appear, rather merely hoping wpf happens produce them in order.
updated add:
here's sketch of how position-aware example might look. although parochial - assumes left-to-right reading text. you'd need more complex internationalized solution.
private string gettextfromvisual(visual v) { drawing textblockdrawing = visualtreehelper.getdrawing(v); var glyphs = new list<positionedglyphs>(); walkdrawingforglyphruns(glyphs, transform.identity, textblockdrawing); // round vertical position, provide tolerance rounding errors // in position calculation. not totally robust - better // identify lines, complicate example... var glyphsorderedbyposition = 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 glyphrundrawing; if (glyphs != null) { var textorigin = glyphs.glyphrun.baselineorigin; point glyphposition = tx.transform(textorigin); glyphlist.add(new positionedglyphs(glyphposition, glyphs)); } else { var g = d drawinggroup; if (g != null) { // drawing groups allowed transform children, need // keep running accumulated transform in tree. matrix current = tx.value; if (g.transform != null) { // note, matrix struct, modifies our local copy without // affecting 1 in 'tx' transforms. current.append(g.transform.value); } var accumulatedtransform = new matrixtransform(current); foreach (drawing child in g.children) { walkdrawingforglyphruns(glyphlist, accumulatedtransform, child); } } } }
Comments
Post a Comment