<TextBlock Text="Stuff on line1
Stuff on line 2"/>
You can use any hexadecimally encoded value to represent a literal. In this case, I used the line feed (char 10). If you want to do "classic" vbCrLf
, then you can use 

By the way, note the syntax: It's the ampersand, a pound, the letter x, then the hex value of the character you want, and then finally a semi-colon.
ALSO: For completeness, you can bind to a text that already has the line feeds embedded in it like a constant in your code behind, or a variable constructed at runtime.
May be you can use the attribute xml:space="preserve" for preserving whitespace in the source XAML
<TextBlock xml:space="preserve">
Stuff on line 1
Stuff on line 2
</TextBlock>
When you need to do it in a string (eg: in your resources) you need to use xml:space="preserve"
and the ampersand character codes:
<System:String x:Key="TwoLiner" xml:space="preserve">First line Second line</System:String>
Or literal newlines in the text:
<System:String x:Key="TwoLiner" xml:space="preserve">First line
Second line</System:String>
Warning: if you write code like the second example, you have inserted either a newline, or a carriage return and newline, depending on the line endings your operating system and/or text editor use. For instance, if you write that and commit it to git from a linux systems, everything may seem fine -- but if someone clones it to Windows, git will convert your line endings to \r\n
and depending on what your string is for ... you might break the world.
Just be aware of that when you're preserving whitespace. If you write something like this:
<System:String x:Key="TwoLiner" xml:space="preserve">
First line
Second line
</System:String>
You've actually added four line breaks, possibly four carriage-returns, and potentially trailing white space that's invisible...
You need just removing <TextBlock.Text>
and simply adding your content as following:
<Grid Margin="20">
<TextBlock TextWrapping="Wrap" TextAlignment="Justify" FontSize="17">
<Bold FontFamily="Segoe UI Light" FontSize="70">I.R. Iran</Bold><LineBreak/>
<Span FontSize="35">I</Span>ran or Persia, officially the <Italic>Islamic Republic of Iran</Italic>,
is a country in Western Asia. The country is bordered on the
north by Armenia, Azerbaijan and Turkmenistan, with Kazakhstan and Russia
to the north across the Caspian Sea.<LineBreak/>
<Span FontSize="10">For more information about Iran see <Hyperlink NavigateUri="http://en.WikiPedia.org/wiki/Iran">WikiPedia</Hyperlink></Span>
<LineBreak/>
<LineBreak/>
<Span FontSize="12">
<Span>Is this page helpful?</Span>
<Button Content="No"/>
<Button Content="Yes"/>
</Span>
</TextBlock>
</Grid>
Note that to do this you need to do it in the Text attribute you cannot use the content like
<TextBlock>Stuff on line1
Stuff on line 2</TextBlock>
Maybe someone prefers
<TextBlock Text="{Binding StringFormat='Stuff on line1{0}Stuff on line2{0}Stuff on line3',
Source={x:Static s:Environment.NewLine}}" />
with xmlns:s="clr-namespace:System;assembly=mscorlib"
.
For those that have tried every answer to this question and are still scratching their heads as to why none of them work for you, you might have ran into a form of the issue I ran into.
My TextBlock.Text
property was inside of a ToolTipService.ToolTip
element and it was databound to a property of an object whose data was being pulled from a SQL stored procedure. Now the data from this particular property within the stored procedure was being pulled from a SQL function.
Since nothing had worked for me, I gave up my search and created the converter class below:
public class NewLineConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var s = string.Empty;
if (value.IsNotNull())
{
s = value.ToString();
if (s.Contains("\\r\\n"))
s = s.Replace("\\r\\n", Environment.NewLine);
if (s.Contains("\\n"))
s = s.Replace("\\n", Environment.NewLine);
if (s.Contains("

"))
s = s.Replace("

", Environment.NewLine);
if (s.Contains("
"))
s = s.Replace("
", Environment.NewLine);
if (s.Contains("
"))
s = s.Replace("
", Environment.NewLine);
if (s.Contains(" "))
s = s.Replace(" ", Environment.NewLine);
if (s.Contains(" "))
s = s.Replace(" ", Environment.NewLine);
if (s.Contains(" "))
s = s.Replace(" ", Environment.NewLine);
if (s.Contains("<br />"))
s = s.Replace("<br />", Environment.NewLine);
if (s.Contains("<LineBreak />"))
s = s.Replace("<LineBreak />", Environment.NewLine);
}
return s;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I ended up having to use the Enivornment.NewLine
method from @dparker's answer. I instructed the converter to look for any possible textual representation of a newline and replace it with Environment.NewLine
.
This worked!
However, I was still perplexed as to why none of the other methods worked with databound properties.
I left a comment on @BobKing's accepted answer:
@BobKing - This doesn't seem to work in the ToolTipService.ToolTip when binding to a field that has the line feeds embedded from a SQL sproc.
He replied with:
@CodeMaverick If you're binding to text with the new lines embedded, they should probably be real char 10 values (or 13's) and not the XML sentinels. This is only if you want to write literal new lines in XAML files.
A light bulb went off!
I went into my SQL function, replaced my textual representations of newlines with ...
CHAR( 13 ) + CHAR( 10 )
... removed the converter from my TextBlock.Text
binding, and just like that ... it worked!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With