Wrapping text in TextBlock
Asked Answered
S

2

11

Are there any possibilities to provide a wordwrap suggestion to a Textblock as you can do in HTML with <SHY> (soft hyphen) or <WBR> (word break) or the even more complicated and less maintainable zero-width-space &#8203;

At the moment the Textblock breaks words just as it sees necessity, ending up with word wraps like

Stackoverflo
w

what I want is:

Stackover-
flow

or at least:

Stackover
flow

If there are recommend ways to achieve the needed, please let me know.

Serosa answered 12/7, 2012 at 11:55 Comment(0)
M
4

Setting TextBlock.IsHypenationEnabled to true would actually do something similar to that, but if you want to use tags, you can use a method like this:

    /// <summary>
    /// Adds break to a TextBlock according to a specified tag
    /// </summary>
    /// <param name="text">The text containing the tags to break up</param>
    /// <param name="tb">The TextBlock we are assigning this text to</param>
    /// <param name="tag">The tag, eg <br> to use in adding breaks</param>
    /// <returns></returns>
    public string WordWrap(string text, TextBlock tb, string tag)
    {
        //get the amount of text that can fit into the textblock
        int len = (int)Math.Round((2 * tb.ActualWidth / tb.FontSize));
        string original = text.Replace(tag, "");
        string ret = "";
        while (original.Length > len)
        {
            //get index where tag occurred
            int i = text.IndexOf(tag);
            //get index where whitespace occurred
            int j = original.IndexOf(" ");
            //does tag occur earlier than whitespace, then let's use that index instead!
            if (j > i && j < len)
                i = j;
            //if we usde index of whitespace, there is no need to hyphenate
            ret += (i == j) ? original.Substring(0, i) + "\n" : original.Substring(0, i) + "-\n";
            //if we used index of whitespace, then let's remove the whitespace
            original = (i == j) ? original.Substring(i + 1) : original.Substring(i);
            text = text.Substring(i + tag.Length);
        }
        return ret + original;
    }

This way you can now say:

textBlock1.Text = WordWrap("StackOver<br>Flow For<br>Ever", textBlock1, "<br>");

This will output:

Just tested

However, using only IsHyphenated without tags, it will be:

IsHypehnated Scenario1

While:

textBlock1.Text = WordWrap("StackOver<br>Flow In<br> U", textBlock1, "<br>");

will output:

Doesn't add <brs> here

And IsHyphenated without tags:

IsHyphenated Scenario 2

EDIT: On reducing font size, I discovered that first code I posted does not prefer adding breaks where whitespaces occur to user specified breaks.

Muckrake answered 13/7, 2012 at 7:6 Comment(3)
Thank you! This looks exactly like what I want. Have to try it out before accepting so.Serosa
Works good, just had to make two minor changes: 1. textBlock1 is replaced woth the parameter tb 2. // get index where tag occurred int i = text.IndexOf(tag); if (i < 0) { return ret + text; }Serosa
Thanks, I actually thought I had updated this... As for checking whether the tag exists, it is not necessary if you're using it for only texts needing the tag, also if you want all your TextBlocks to have this feature, you should make a custom control and override the text change property...Muckrake
H
3

Use the TextFormatter in conjunction with a custom TextSource to control how the text is broken up and wrapped.

You need to derive a class from TextSource and in your implementation analyse your content/string and provide your wrapping rules, e.g. looking for your <wbr> tag...when you see a tag you return a TextEndOfLine else you return a TextCharacters.

An example which could help in implementing a TextSource is here:

For a very advanced example look at "AvalonEdit" which also uses it:

You could also investigate GlyphRun if you don't need rich formatting.

Hootman answered 12/7, 2012 at 13:27 Comment(2)
Those examples are very good! +1 Although, there must be an easier way to do this. Perhaps a wrapping textbox that understands a soft hyphen or something like that.Serosa
You could use a RichTextBox and then just provide suitably defined RTF.Hootman

© 2022 - 2024 — McMap. All rights reserved.