I have a few TextBlocks in WPF in a Grid that I would like to scale depending on their available width / height. When I searched for automatically scaling Font size the typical suggestion is to put the TextBlock into a ViewBox.
So I did this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Viewbox MaxHeight="18" Grid.Column="0" Stretch="Uniform" Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding Text1}" />
</Viewbox>
<Viewbox MaxHeight="18" Grid.Column="1" Stretch="Uniform" Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding Text2}" />
</Viewbox>
<Viewbox MaxHeight="18" Grid.Column="2" Stretch="Uniform" Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding Text3}" />
</Viewbox>
</Grid>
And it scales the font for each TextBlock automatically. However, this looks funny because if one of the TextBlocks has longer text then it will be in a smaller font while it's neighboring grid elements will be in a larger font. I want the Font size to scale by group, perhaps it would be nice if I could specify a "SharedSizeGroup" for a set of controls to auto size their font.
e.g.
The first text blocks text might be "3/26/2013 10:45:30 AM", and the second TextBlocks text might say "FileName.ext". If these are across the width of a window, and the user begins resizing the window smaller and smaller. The date will start making its font smaller than the file name, depending on the length of the file name.
Ideally, once one of the text fields starts to resize the font point size, they would all match. Has anyone came up with a solution for this or can give me a shot at how you would make it work? If it requires custom code then hopefully we / I could repackage it into a custom Blend or Attached Behavior so that is re-usable for the future. I think it is a pretty general problem, but I wasn't able to find anything on it by searching.
Update
I tried Mathieu's suggestion and it sort of works, but it has some side-effects:
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="270" Width="522">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Fill="SkyBlue" />
<Viewbox Grid.Row="1" MaxHeight="30" Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="col"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="col"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="col"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="SomeLongText" Margin="5" />
<TextBlock Grid.Column="1" Text="TextA" Margin="5" />
<TextBlock Grid.Column="2" Text="TextB" Margin="5" />
</Grid>
</Viewbox>
</Grid>
</Window>
Honestly, missing hte proportional columns is probably fine with me. I wouldn't mind it AutoSizing the columns to make smart use of the space, but it has to span the entire width of the window.
Notice without maxsize, in this extended example the text is too large:
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="270" Width="522">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Fill="SkyBlue" />
<Viewbox Grid.Row="1" Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="col"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="col"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="col"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="SomeLongText" Margin="5" />
<TextBlock Grid.Column="1" Text="TextA" Margin="5" />
<TextBlock Grid.Column="2" Text="TextB" Margin="5" />
</Grid>
</Viewbox>
</Grid>
Here, I would want to limit how big the font can get, so it doesn't waste vertical window real estate. I'm expecting the output to be aligned left, center, and right with the Font being as big as possible up to the desired maximum size.
@adabyron
The solution you propose is not bad (And is the best yet) but it does have some limitations. For example, initially I wanted my columns to be proportional (2nd one should be centered). For example, my TextBlocks might be labeling the start, center, and stop of a graph where alignment matters.
<Window x:Class="WpfApplication6.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:b="clr-namespace:WpfApplication6.Behavior"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Fill="SkyBlue" />
<Line X1="0.5" X2="0.5" Y1="0" Y2="1" Stretch="Fill" StrokeThickness="3" Stroke="Red" />
<Grid Grid.Row="1">
<i:Interaction.Behaviors>
<b:MoveToViewboxBehavior />
</i:Interaction.Behaviors>
<Viewbox Stretch="Uniform" />
<ContentPresenter >
<ContentPresenter.Content>
<Grid x:Name="TextBlockContainer">
<Grid.Resources>
<Style TargetType="TextBlock" >
<Setter Property="FontSize" Value="16" />
<Setter Property="Margin" Value="5" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="SomeLongText" VerticalAlignment="Center" HorizontalAlignment="Center" />
<TextBlock Grid.Column="2" Text="TextA" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Grid.Column="4" Text="TextB" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ContentPresenter.Content>
</ContentPresenter>
</Grid>
</Grid>
</Window>
And here is the result. Notice it does not know that it is getting clipped early on, and then when it substitutes ViewBox it looks as if the Grid defaults to column size "Auto" and no longer aligns center.
See Question&Answers more detail:
os