Click here to Skip to main content
15,881,630 members
Articles / Desktop Programming / WPF
Tip/Trick

Custom Text Wrapping in WPF TextBlocks

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
13 Jul 2012CPOL2 min read 22.2K   3  
This tip demonstrates how to wrap text in WPF - similar to using &shy or <wbr. in html

Introduction

I was intrigued by this question on Stack Overflow. The OP wanted to be able to wrap text based on a custom tag just like how it is done in HTML using &shy or <wbr>. While it is possible to imitate a feature close to this by setting TextBlock.IsHyphenated to true, I just decided to write a simple method that could emulate this feature in WPF.

Background

My idea was simply to write a code that would simply strip and store the position of tags in a supplied text and insert newlines by making a choice of where to insert based on the number of characters that can be displayed in a single line of the control. The method also had to be able to make a choice between the break tag and whitespace characters.

Using the Code

The code is quite simple to use. It accepts three parameters, and can be called as follows:

C#
textBlock1.Text = WordWrap("Code<br>project <br>Today", textBlock1, "<br>");  

In the above example, it's assumed that the break tag is <br>, so it's obvious that the method can be made to use a default tag to make using it simpler.

Here's a listing of the full code:

C#
/// <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;
}

Points of Interest

The major interesting thing I encountered was calculating the amount of text that could fit into a single line of a WPF TextBlock control. I knew about Graphics.MeasureString method for WinForms and TextFormatter for WPF, but I wanted to avoid the latter. A random guess made me try TextBlock.Width / TextBlock.FontSize, but this of course did not work since the TextBlock width was set to auto. However with little experimentation, I discovered that...

C#
(int)Math.Round((2 * TextBlock.ActualWidth / TextBlock.FontSize));   

...works well.

I also believe this method should be able to work for other text supporting WPF controls.

History

This if the first version of the code. There could be possible improvements in the future based on suggestions, bugs or performance.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Robotic Systems
Nigeria Nigeria
Chibueze Opata is a software developer studying Computer Science at the University of Nigeria Nsukka. He is also the developer of RoboSAM - A free and unique antivirus solution that relies minimally on signature updates for malware detections.

Comments and Discussions

 
-- There are no messages in this forum --