Reputation: 8192
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 ​
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.
Upvotes: 11
Views: 3397
Reputation: 10044
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:
However, using only IsHyphenated without tags, it will be:
While:
textBlock1.Text = WordWrap("StackOver<br>Flow In<br> U", textBlock1, "<br>");
will output:
And IsHyphenated without tags:
EDIT: On reducing font size, I discovered that first code I posted does not prefer adding breaks where whitespaces occur to user specified breaks.
Upvotes: 4
Reputation: 12550
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.
Upvotes: 3