Search code examples
c#wpftextblock

Wrapping text in TextBlock


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.


Solution

  • Setting TextBlock.IsHyphenationEnabled 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  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.