Is it possible to display the text in a TextBlock vertically so that all letters are stacked upon each other (not rotated with LayoutTransform)?
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.
<ItemsControl ItemsSource="{Binding Source='some text'}"/>
–
Excommunication 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>
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.
Just use a simple LayoutTransform..
<Label Grid.Column="0" Content="Your Text Here" HorizontalContentAlignment="Center">
<Label.LayoutTransform>
<TransformGroup>
<RotateTransform Angle="90" />
<ScaleTransform ScaleX="-1" ScaleY="-1"/>
</TransformGroup>
</Label.LayoutTransform>
</Label>
It's doable:
Your TextBlock
's TextAlignment
property should be set to Center
:
<TextBlock Name="textBlock1" TextAlignment="Center" Text="Stacked!" />
Then add NewLine
s 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...)
Below XAML code changes the angle of text displayed in a textblock.
<TextBlock Height="14"
x:Name="TextBlock1"
Text="Vertical Bottom to Up" Margin="73,0,115,0" RenderTransformOrigin="0.5,0.5" >
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
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!
create a stackpanel with a bunch ot textblocks that take one char
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" />
Make an image and fill the block with the image, use photoshop or something designed to manipulate text instead of fiddling in code ?
This code allows to have vertical text stacking and horizontal centered letters.
<ItemsControl Grid.Row="1"
Grid.Column="0"
ItemsSource="YOUR TEXT HERE"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
HorizontalAlignment="Center"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
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.
You could also use the "RUN" binding
In the App.xaml file use something like this:
<Application x:Class="Some.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:commands="clr-namespace:Deridiam.Helper.Commands"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
ShutdownMode="OnMainWindowClose"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<commands:HorizontalToVertical x:Key="HorizontalToVertical_Command"></commands:HorizontalToVertical>
<ControlTemplate x:Key="VerticalCell" TargetType="ContentControl">
<TextBlock Text="{TemplateBinding Content}" Foreground="Black"
TextAlignment="Center" FontWeight="Bold" VerticalAlignment="Center"
TextWrapping="Wrap" Margin="0" FontSize="10">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding ConvertToVerticalCmd, Source={StaticResource HorizontalToVertical_Command}}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBlock}}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</ControlTemplate>
</Application.Resources>
Create the command class binded to the textblock using i:Interaction.Triggers on the Loaded event in the app.xaml example
namespace Deridiam.Helper.Commands
{
public class HorizontalToVertical
{
private ICommand _convertToVerticalCommand;
public ICommand ConvertToVerticalCmd =>
_convertToVerticalCommand ?? (_convertToVerticalCommand = new RelayCommand(
x =>
{
var tBlock = x as TextBlock;
var horizontalText = tBlock.Text;
tBlock.Text = "";
horizontalText.Select(c => c).ToList().ForEach(c =>
{
if (c.ToString() == " ")
{
tBlock.Inlines.Add("\n");
//tBlock.Inlines.Add("\n");
}
else
{
tBlock.Inlines.Add((new Run(c.ToString())));
tBlock.Inlines.Add(new LineBreak());
}
});
}));
}
}
Finally in the .xaml file where you want the vertical text to be shown
<ContentControl Width="15" Content="Vertical Text" Template="{StaticResource VerticalCell}">
</ContentControl>
Will result in:
V
e
r
t
i
c
a
l
T
e
x
t
none of the above solutions solved my problem (some come close), so I'm here to post my solution and maybe help someone. The accepted solution helped me, but the text is not aligned to the center.
<ItemsControl ItemsSource="{Binding SomeStringProperty, FallbackValue=Group 1}" Margin="5"
TextElement.FontSize="16"
TextElement.FontWeight="Bold"
TextBlock.TextAlignment="Center"
HorizontalAlignment="Center"
VerticalAlignment="Center" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding }" HorizontalAlignment="Center" />
</DataTemplate>
</ItemsControl.ItemTemplate>
I will offer a solution based on the converter:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace Converters
{
[ValueConversion(typeof(object), typeof(string))]
public class InsertLineBreakConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter != null)
value = parameter;
if (value == null)
return null;
if (!(value is string str))
str = value.ToString();
return string.Join(Environment.NewLine, (IEnumerable<char>) str);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static InsertLineBreakConverter Instance { get; } = new InsertLineBreakConverter();
}
public class InsertLineBreakConverterExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
=> InsertLineBreakConverter.Instance;
}
}
Usage examples:
<TextBlock Text="{Binding Property, Converter={cnvs:InsertLineBreakConverter}}"/>
<TextBlock Text="{Binding Converter={cnvs:InsertLineBreakConverter}, ConverterParameter='Some Text'}"/>
© 2022 - 2024 — McMap. All rights reserved.