[xaml] Newline in string attribute

How can I add a line break to text when it is being set as an attribute i.e.:

<TextBlock Text="Stuff on line1 \n Stuff on line2" />

Breaking it out into the exploded format isn't an option for my particular situation. What I need is some way to emulate the following:

<TextBlock>
  <TextBlock.Text>
    Stuff on line1 <LineBreak/>
    Stuff on line2
  </TextBlock.Text>
<TextBlock/>

This question is related to xaml

The answer is


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>

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>

enter image description here


<TextBlock>
    Stuff on line1 <LineBreak/>
    Stuff on line2
</TextBlock>

not that it's important to know but what you specify between the TextBlock tags is called inline content and goes into the TextBlock.Inlines property which is a InlineCollection and contains items of type Inline. Subclasses of Inline are Run and LineBreak, among others. see TextBlock.Inlines


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".


I have found this helpful, but ran into some errors when adding it to a "Content=..." tag in XAML.

I had multiple lines in the content, and later found out that the content kept white spaces even though I didn't specify that. so to get around that and having it "ignore" the whitespace, I implemented such as this.

<ToolTip Width="200" Style="{StaticResource ToolTip}" 
         Content="'Text Line 1' 
                   &#x0a;&#x0d;'Text Line 2' 
                   &#x0a;&#x0d;'Text Line 3'"/>

hope this helps someone else.

(The output is has the three text lines with an empty line in between each.)


Also doesn't work with

<TextBlock><TextBlock.Text>NO USING ABOVE TECHNIQUE HERE</TextBlock.Text>

No big deal, just needed to use

<TextBlock Text="Cool &#x0a;Newline trick" />

instead.


I realize this is on older question but just wanted to add that

Environment.NewLine

also works if doing this through code.


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&#10;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...


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("&#x0a;&#x0d;"))
                s = s.Replace("&#x0a;&#x0d;", Environment.NewLine);

            if (s.Contains("&#x0a;"))
                s = s.Replace("&#x0a;", Environment.NewLine);

            if (s.Contains("&#x0d;"))
                s = s.Replace("&#x0d;", Environment.NewLine);

            if (s.Contains("&#10;&#13;"))
                s = s.Replace("&#10;&#13;", Environment.NewLine);

            if (s.Contains("&#10;"))
                s = s.Replace("&#10;", Environment.NewLine);

            if (s.Contains("&#13;"))
                s = s.Replace("&#13;", 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!


Note that to do this you need to do it in the Text attribute you cannot use the content like

<TextBlock>Stuff on line1&#x0a;Stuff on line 2</TextBlock>

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("&#x0a;&#x0d;"))
                s = s.Replace("&#x0a;&#x0d;", Environment.NewLine);

            if (s.Contains("&#x0a;"))
                s = s.Replace("&#x0a;", Environment.NewLine);

            if (s.Contains("&#x0d;"))
                s = s.Replace("&#x0d;", Environment.NewLine);

            if (s.Contains("&#10;&#13;"))
                s = s.Replace("&#10;&#13;", Environment.NewLine);

            if (s.Contains("&#10;"))
                s = s.Replace("&#10;", Environment.NewLine);

            if (s.Contains("&#13;"))
                s = s.Replace("&#13;", 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!


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".


Code behind solution

private void Button1_Click(object sender, RoutedEventArgs e)
{
    System.Text.StringBuilder myStringBuilder = new System.Text.StringBuilder();
    myStringBuilder.Append("Orange").AppendLine();
    myStringBuilder.Append("").AppendLine();
    myStringBuilder.Append("Apple").AppendLine();
    myStringBuilder.Append("Banana").AppendLine();
    myStringBuilder.Append("").AppendLine();
    myStringBuilder.Append("Plum").AppendLine();
    TextBox1.Text = myStringBuilder.ToString();
}

<TextBlock>
    Stuff on line1 <LineBreak/>
    Stuff on line2
</TextBlock>

not that it's important to know but what you specify between the TextBlock tags is called inline content and goes into the TextBlock.Inlines property which is a InlineCollection and contains items of type Inline. Subclasses of Inline are Run and LineBreak, among others. see TextBlock.Inlines


Also doesn't work with

<TextBlock><TextBlock.Text>NO USING ABOVE TECHNIQUE HERE</TextBlock.Text>

No big deal, just needed to use

<TextBlock Text="Cool &#x0a;Newline trick" />

instead.


I realize this is on older question but just wanted to add that

Environment.NewLine

also works if doing this through code.


Code behind solution

private void Button1_Click(object sender, RoutedEventArgs e)
{
    System.Text.StringBuilder myStringBuilder = new System.Text.StringBuilder();
    myStringBuilder.Append("Orange").AppendLine();
    myStringBuilder.Append("").AppendLine();
    myStringBuilder.Append("Apple").AppendLine();
    myStringBuilder.Append("Banana").AppendLine();
    myStringBuilder.Append("").AppendLine();
    myStringBuilder.Append("Plum").AppendLine();
    TextBox1.Text = myStringBuilder.ToString();
}

<TextBox 
    Name="myTextBox" 
    TextWrapping="Wrap" 
    AcceptsReturn="True" 
    VerticalScrollBarVisibility="Visible" />

Note that to do this you need to do it in the Text attribute you cannot use the content like

<TextBlock>Stuff on line1&#x0a;Stuff on line 2</TextBlock>

<TextBox 
    Name="myTextBox" 
    TextWrapping="Wrap" 
    AcceptsReturn="True" 
    VerticalScrollBarVisibility="Visible" />

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&#10;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...


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>

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>

enter image description here


I have found this helpful, but ran into some errors when adding it to a "Content=..." tag in XAML.

I had multiple lines in the content, and later found out that the content kept white spaces even though I didn't specify that. so to get around that and having it "ignore" the whitespace, I implemented such as this.

<ToolTip Width="200" Style="{StaticResource ToolTip}" 
         Content="'Text Line 1' 
                   &#x0a;&#x0d;'Text Line 2' 
                   &#x0a;&#x0d;'Text Line 3'"/>

hope this helps someone else.

(The output is has the three text lines with an empty line in between each.)