tags:

views:

5578

answers:

11

Is it possible to display the text in a TextBlock vertically so that all letters are stacked upon each other (not rotated with LayoutTransform)?

+1  A: 

I don't think there is a straighforward of doing this withought changing the way the system inherently laysout text. The easiest solution would be to change the width of the textblock and supply a few extra properties like this:

<TextBlock TextAlignment="Center" FontSize="14" FontWeight="Bold" Width="10" TextWrapping="Wrap">THIS IS A TEST</TextBlock>

This is hacky, but it does work.

Micah
+4  A: 

It's doable:

Your TextBlock's TextAlignment property should be set to Center:

<TextBlock Name="textBlock1" TextAlignment="Center" Text="Stacked!" />

Then add NewLines between every character:

textBlock1.Text =
    String.Join(
        Environment.NewLine,
        textBlock1.Text.Select(c => new String(c, 1)).ToArray());

(Uses System.Linq to create an array of strings from the individual characters in the original string. I'm sure there are other ways of doing that...)

Lette
Thas a pretty sexy line of code :-)
Dested
Well, thank you! ;-)
Lette
@Lette I know this was quite a while ago but this seems like a very inefficient way of doing it. Think if you set the text many times
Oskar Kjellin
You're right, Oskar. If performance was an issue, I would most definitely come up with a different solution.
Lette
A: 

Here's a way to insert a '\n' after every character in the text of the TextBlock, that way making it display vertically:

<TextBlock x:Name="VertTextBlock" Text="Vertical Text" Loaded="VertTextBlock_Loaded"></TextBlock>

Then, in the Loaded event handler, you say:

TextBlock tb = sender as TextBlock;
StringBuilder sb = new StringBuilder(tb.Text);
int len = tb.Text.Length * 2;

for (int i = 1; i < len; i += 2)
{
    sb.Insert(i, '\n');
}

tb.Text = sb.ToString();

That solution was proposed by Lette, but I believe my implementation incurs less overhead.

Boyan
it has quadratic complexity.
usr
A: 
<linebreak/> can be used to show data in two lines
Amit
+1  A: 

Just in case anybody still comes across this post... here is a simple 100% xaml solution.

    <TabControl TabStripPlacement="Left">
        <TabItem Header="Tab 1">
            <TabItem.LayoutTransform>
                <RotateTransform Angle="-90"></RotateTransform>      
            </TabItem.LayoutTransform>
            <TextBlock> Some Text for tab 1</TextBlock>
        </TabItem>
        <TabItem Header="Tab 2">
            <TabItem.LayoutTransform>
                <RotateTransform Angle="-90"></RotateTransform>
            </TabItem.LayoutTransform>
            <TextBlock> Some Text for tab 2</TextBlock>
        </TabItem>
    </TabControl>
esko22
I think this doesn't answer the original question. What you wrote rotates the text as a whole, so the letters are still beside each other just facing a different way. What I (and the other answerers) understood was that the question was how to stack the letters so they are still right-side-up, but above and below one another instead of beside one another. There is a clever way of doing this which nobody has posted yet. I will do so presently.
Ray Burns
Thanks Ray. You are absolutely correct... I totally missed the premise.
esko22
Fantastic bit of code! Thank you, it's exactly what I was looking for.
wonea
+9  A: 

Nobody has yet mentioned the obvious and trivial way to stack the letters of an arbitrary string vertically (without rotating them) using pure XAML:

<ItemsControl
  ItemsSource="Text goes here, or you could use a binding to a string" />

This simply lays out the text vertically by recognizing the fact that the string is an IEnumerable and so ItemsControl can treat each character in the string as a separate item. The default panel for ItemsControl is a StackPanel, so the characters are laid out vertically.

Note: For precise control over horizontal positioning, vertical spacing, etc, the ItemContainerStyle and ItemTemplate properties can be set on the ItemsControl.

Ray Burns
I tested your solution and the provided xaml does not work (.net 3.5, parser error). But it works if you bind to a string property or set the item source through code to a string.Would be nice to know with which .net version you tested the xaml. at the moment i cannot verify if the behaviour changed to .net 4.0.Never the less a nice solution and what i was looking for. :-)
MarioH
A: 

create a stackpanel with a bunch ot textblocks that take one char

denis morozov
A: 

make the text container's max width to allow for one char only and wrap the text:

<TextBlock TextWrapping="Wrap" MaxWidth="8" TextAlignment="Center" Text="stack"/>

denis morozov

A: 

the accepted answer suggested by Ray Burns does not work for me on .net 4.0. Here is how I did it:

pull in the mscorlib

xmlns:s="clr-namespace:System;assembly=mscorlib"

put in your usercontrol/window/page resources

<s:String x:Key="SortString">Sort</s:String>

and use it like this

<ItemsControl ItemsSource="{Binding Source={StaticResource SortString}}" Margin="5,-1,0,0"   />    

hope it helps!

TWood
A: 

TWood, your solution works in kaxaml, and so does this slightly stripped version:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:s="clr-namespace:System;assembly=mscorlib">
  <Page.Resources>
    <s:String x:Key="SortString">Sort</s:String>
  </Page.Resources>
  <Grid>
    <ItemsControl ItemsSource="{StaticResource SortString}" Margin="5,-1,0,0"   />
  </Grid>
</Page>
FocusedWolf