Как автоматически масштабировать размер шрифта для группы элементов управления?

У меня есть несколько TextBlocks в WPF в сетке, которые я хотел бы масштабировать в зависимости от их ширины / высоты. Когда я искал автоматическое масштабирование размера шрифта, типичным предложением было поместить TextBlock в ViewBox.

Итак, я сделал это:

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

И он автоматически масштабирует шрифт для каждого TextBlock. Однако это выглядит забавно, потому что, если один из TextBlocks имеет более длинный текст, он будет иметь меньший шрифт, в то время как соседние элементы сетки будут иметь больший шрифт. Я хочу, чтобы размер шрифта масштабировался по группам, возможно, было бы неплохо, если бы я мог указать «SharedSizeGroup» для набора элементов управления для автоматического изменения размера их шрифта.

например

Первый текстовый текстовый блок может быть «26.03.2013 10:45:30», а второй текстовый текстовый блок может содержать «FileName.ext». Если они по ширине окна, и пользователь начинает изменять размер окна все меньше и меньше. Дата начнет делать свой шрифт меньше, чем имя файла, в зависимости от длины имени файла.

В идеале, как только одно из текстовых полей начнет изменять размер шрифта, все они будут совпадать. Кто-нибудь придумал решение для этого или может дать мне представление о том, как вы могли бы заставить его работать? Если для этого требуется пользовательский код, то, надеюсь, мы / я могли бы упаковать его в пользовательский Blend или Attached Behavior, чтобы его можно было использовать в будущем. Я думаю, что это довольно общая проблема, но я не смог ничего найти по ней с помощью поиска.

Обновить Я попробовал предложение Матье, и оно вроде работает, но у него есть некоторые побочные эффекты:

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

Честно говоря, мне не хватает пропущенных пропорциональных столбцов. Я не возражаю против автоматического изменения размеров столбцов, чтобы разумно использовать пространство, но оно должно охватывать всю ширину окна.

Обратите внимание без maxsize, в этом расширенном примере текст слишком велик:

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

Здесь я бы хотел ограничить размер шрифта, чтобы не тратить пространство на вертикальные окна.Я ожидаю, что выходные данные будут выровнены по левому, центральному и правому краям, причем шрифт будет максимально большим до желаемого максимального размера.

@adabyron

Решение, которое вы предлагаете, неплохое (и пока лучшее), но оно имеет некоторые ограничения. Например, изначально я хотел, чтобы мои столбцы были пропорциональными (2-й должен быть по центру). Например, мои TextBlocks могут маркироватьначало, центр и остановка графика где выравнивание имеет значение.

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

И вот результат. Обратите внимание, что он не знает, что он рано обрезается, а затем, когда он заменяет ViewBox, он выглядит так, как будто Grid по умолчанию имеет размер столбца «Auto» и больше не выравнивает центр.

Ответы на вопрос(6)

Ваш ответ на вопрос