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 ­
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:
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:
public string WordWrap(string text, TextBlock tb, string tag)
{
int len = (int)Math.Round((2 * tb.ActualWidth / tb.FontSize));
string original = text.Replace(tag, "");
string ret = "";
while (original.Length > len)
{
int i = text.IndexOf(tag);
int j = original.IndexOf(" ");
if (j > i && j < len)
i = j;
ret += (i == j) ? original.Substring(0, i) + "\n" : original.Substring(0, i) + "-\n";
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...
(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.