如何自动缩放一组控件的字体大小?

我有一个WPF中的几个TextBlocks在一个网格,我想缩放取决于其可用的宽度/高度。 当我search自动缩放字体大小时,典型的build议是将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”作为一组控件来自动调整字体大小,那么可能会很好。

例如

第一个文本块文本可能是“3/26/2013 10:45:30 AM”,第二个TextBlocks文本可能会说“FileName.ext”。 如果这些是在一个窗口的宽度,用户开始调整窗口的大小越来越小。 date将开始使其字体小于文件名,这取决于文件名的长度。

理想情况下,一旦文本字段之一开始调整字体大小的大小,他们都将匹配。 有没有人想出了一个解决scheme,或者可以给我一个如何使它的工作原理? 如果它需要自定义代码,那么希望我们/我可以重新打包到一个自定义的混合或附加行为,以便将来可重用。 我认为这是一个相当普遍的问题,但我无法通过searchfind任何东西。


更新我尝试了Mathieu的build议,它有点作品,但它有一些副作用:

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

副作用

老实说,丢失比例列对我来说可能是好的。 我不介意AutoSizing的列使智能使用的空间,但它必须跨越整个窗口的宽度。

注意没有最大化,在这个扩展的例子中,文字太大了:

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

文字太大而没有MaxSize

在这里,我想限制字体可以得到多大,所以它不浪费垂直窗口的房地产。 我期望输出是左alignment,中间和右alignment的字体尽可能大到所需的最大尺寸。


@adabyron

你提出的解决scheme并不差(而且是最好的),但是它有一些限制。 例如,最初我想让我的列成比例(第二个应居中)。 例如,我的TextBlocks可能会标注alignment很重要的graphics开始,中间和停止

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

这是结果。 注意,它并不知道它在早期被剪切,然后当它replaceViewBox时,它看起来好像网格默认为列大小“自动”,不再alignment中心。

用adabyron的建议来缩放

我想编辑我已经提供的答案,但后来决定发布一个新的更有意义,因为它实际上取决于我所喜欢的要求。 这里可能更适合Alan的想法,因为

  • 中间的文本块停留在窗口的中间
  • 由于高度限制,可以调整字体大小
  • 相当多一点通用
  • 没有涉及的Viewbox

在这里输入图像说明

在这里输入图像说明

另一个有这个优点

  • 文本块的空间分配更有效率(没有不必要的边距)
  • 文本块可能有不同的字体大小

我也在StackPanel / DockPaneltypes的顶级容器中testing了这个解决scheme,performance得体面。

请注意,通过玩弄列/行宽/高度(自动/星号),您可以获得不同的行为。 所以也可以将所有三个文本块列星形化,但是这意味着宽度限制确实发生得更早,并且有更多的余量。 或者,如果网格所在的行是自动大小的,则高度限制将不会发生。

XAML:

 <Window x:Class="WpfApplication1.MainWindow" 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:beh="clr-namespace:WpfApplication1.Behavior" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="0.9*"/> <RowDefinition Height="0.1*" /> </Grid.RowDefinitions> <Rectangle Fill="DarkOrange" /> <Grid x:Name="TextBlockContainer" Grid.Row="1" > <i:Interaction.Behaviors> <beh:ScaleFontBehavior MaxFontSize="32" /> </i:Interaction.Behaviors> <Grid.Resources> <Style TargetType="TextBlock" > <Setter Property="Margin" Value="5" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> </Grid.Resources> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="SomeLongText" /> <TextBlock Grid.Column="1" Text="TextA" HorizontalAlignment="Center" /> <TextBlock Grid.Column="2" Text="TextB" HorizontalAlignment="Right" /> </Grid> </Grid> </Window> 

ScaleFontBehavior:

 using System; using System.Collections.Generic; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Interactivity; using System.Windows.Media; using WpfApplication1.Helpers; namespace WpfApplication1.Behavior { public class ScaleFontBehavior : Behavior<Grid> { // MaxFontSize public double MaxFontSize { get { return (double)GetValue(MaxFontSizeProperty); } set { SetValue(MaxFontSizeProperty, value); } } public static readonly DependencyProperty MaxFontSizeProperty = DependencyProperty.Register("MaxFontSize", typeof(double), typeof(ScaleFontBehavior), new PropertyMetadata(20d)); protected override void OnAttached() { this.AssociatedObject.SizeChanged += (s, e) => { CalculateFontSize(); }; } private void CalculateFontSize() { double fontSize = this.MaxFontSize; List<TextBlock> tbs = VisualHelper.FindVisualChildren<TextBlock>(this.AssociatedObject); // get grid height (if limited) double gridHeight = double.MaxValue; Grid parentGrid = VisualHelper.FindUpVisualTree<Grid>(this.AssociatedObject.Parent); if (parentGrid != null) { RowDefinition row = parentGrid.RowDefinitions[Grid.GetRow(this.AssociatedObject)]; gridHeight = row.Height == GridLength.Auto ? double.MaxValue : this.AssociatedObject.ActualHeight; } foreach (var tb in tbs) { // get desired size with fontsize = MaxFontSize Size desiredSize = MeasureText(tb); double widthMargins = tb.Margin.Left + tb.Margin.Right; double heightMargins = tb.Margin.Top + tb.Margin.Bottom; double desiredHeight = desiredSize.Height + heightMargins; double desiredWidth = desiredSize.Width + widthMargins; // adjust fontsize if text would be clipped vertically if (gridHeight < desiredHeight) { double factor = (desiredHeight - heightMargins) / (this.AssociatedObject.ActualHeight - heightMargins); fontSize = Math.Min(fontSize, MaxFontSize / factor); } // get column width (if limited) ColumnDefinition col = this.AssociatedObject.ColumnDefinitions[Grid.GetColumn(tb)]; double colWidth = col.Width == GridLength.Auto ? double.MaxValue : col.ActualWidth; // adjust fontsize if text would be clipped horizontally if (colWidth < desiredWidth) { double factor = (desiredWidth - widthMargins) / (col.ActualWidth - widthMargins); fontSize = Math.Min(fontSize, MaxFontSize / factor); } } // apply fontsize (always equal fontsizes) foreach (var tb in tbs) { tb.FontSize = fontSize; } } // Measures text size of textblock private Size MeasureText(TextBlock tb) { var formattedText = new FormattedText(tb.Text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface(tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch), this.MaxFontSize, Brushes.Black); // always uses MaxFontSize for desiredSize return new Size(formattedText.Width, formattedText.Height); } } } 

VisualHelper:

 public static List<T> FindVisualChildren<T>(DependencyObject obj) where T : DependencyObject { List<T> children = new List<T>(); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { var o = VisualTreeHelper.GetChild(obj, i); if (o != null) { if (o is T) children.Add((T)o); children.AddRange(FindVisualChildren<T>(o)); // recursive } } return children; } public static T FindUpVisualTree<T>(DependencyObject initial) where T : DependencyObject { DependencyObject current = initial; while (current != null && current.GetType() != typeof(T)) { current = VisualTreeHelper.GetParent(current); } return current as T; } 

把你的网格放在视图框,这将扩大整个网格:

 <Viewbox Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding Text1}" Margin="5" /> <TextBlock Grid.Column="1" Text="{Binding Text2}" Margin="5" /> <TextBlock Grid.Column="2" Text="{Binding Text3}" Margin="5" /> </Grid> </Viewbox> 

我想我知道要走的路,将其余的留给你。 在这个例子中,我使用转换器(下面的转换器)将FontSize绑定到TextBlock的ActualHeight:

 <Window x:Class="MyNamespace.Test" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Converters="clr-namespace:UpdateYeti.Converters" Title="Test" Height="570" Width="522"> <Grid Height="370" Width="522"> <Grid.Resources> <Converters:HeightToFontSizeConverter x:Key="conv" /> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Rectangle Grid.Row="0" Fill="SkyBlue" /> <Grid Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="60" Background="Beige"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="SomeLongText" Margin="5" FontSize="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource conv}}" /> <TextBlock Grid.Column="1" Text="TextA" Margin="5" HorizontalAlignment="Center" FontSize="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource conv}}" /> <TextBlock Grid.Column="2" Text="TextB" Margin="5" FontSize="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource conv}}" /> </Grid> </Grid> </Window> [ValueConversion(typeof(double), typeof(double))] class HeightToFontSizeConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // here you can use the parameter that you can give in here via setting , ConverterParameter='something'} or use any nice login with the VisualTreeHelper to make a better return value, or maybe even just hardcode some max values if you like var height = (double)value; return .65 * height; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

一般的评论:整个文本缩放的一个可能的替代scheme可能是在TextBlocks上使用TextTrimming。

我一直在努力寻找解决scheme。 使用viewbox真的很难与任何布局调整混合。 最糟糕的是,ActualWidth等在视图框内不会改变。 所以我最终决定只在绝对必要的时候使用viewbox,这就是裁剪时会发生的情况。 因此,我根据可用空间在ContentPresenter和Viewbox之间移动内容。


在这里输入图像说明

在这里输入图像说明


这个解决scheme不像我想的那样通用,主要是MoveToViewboxBehavior确实假定它被连接到具有以下结构的网格。 如果这不能适应,那么行为将很可能需要调整。 创build一个用户控件并表示必要的部分(PART _…)可能是一个有效的select。

请注意,我已经将网格的列从三个扩展到五个,因为这使得解决scheme变得更容易。 这意味着中间的文本块将不会完全位于绝对坐标的中间,而是位于左右文本块之间。

 <Grid > <!-- MoveToViewboxBehavior attached to this grid --> <Viewbox /> <ContentPresenter> <ContentPresenter.Content> <Grid x:Name="TextBlockContainer"> <TextBlocks ... /> </Grid> </ContentPresenter.Content> </ContentPresenter> </Grid> 

XAML:

 <Window x:Class="WpfApplication1.MainWindow" 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:beh="clr-namespace:WpfApplication1.Behavior" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Rectangle Grid.Row="0" Fill="SkyBlue" /> <Grid Grid.Row="1"> <i:Interaction.Behaviors> <beh: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="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="SomeLongText" /> <TextBlock Grid.Column="2" Text="TextA" /> <TextBlock Grid.Column="4" Text="TextB" /> </Grid> </ContentPresenter.Content> </ContentPresenter> </Grid> </Grid> </Window> 

MoveToViewBoxBehavior:

 using System; using System.Collections.Generic; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Interactivity; using System.Windows.Media; using WpfApplication1.Helpers; namespace WpfApplication1.Behavior { public class MoveToViewboxBehavior : Behavior<Grid> { // IsClipped public bool IsClipped { get { return (bool)GetValue(IsClippedProperty); } set { SetValue(IsClippedProperty, value); } } public static readonly DependencyProperty IsClippedProperty = DependencyProperty.Register("IsClipped", typeof(bool), typeof(MoveToViewboxBehavior), new PropertyMetadata(false, OnIsClippedChanged)); private static void OnIsClippedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var beh = (MoveToViewboxBehavior)sender; Grid grid = beh.AssociatedObject; Viewbox vb = VisualHelper.FindVisualChild<Viewbox>(grid); ContentPresenter cp = VisualHelper.FindVisualChild<ContentPresenter>(grid); if ((bool)e.NewValue) { // is clipped, so move content to Viewbox UIElement element = cp.Content as UIElement; cp.Content = null; vb.Child = element; } else { // can be shown without clipping, so move content to ContentPresenter cp.Content = vb.Child; vb.Child = null; } } protected override void OnAttached() { this.AssociatedObject.SizeChanged += (s, e) => { IsClipped = CalculateIsClipped(); }; } // Determines if the width of all textblocks within TextBlockContainer (using MaxFontSize) are wider than the AssociatedObject grid private bool CalculateIsClipped() { double totalDesiredWidth = 0d; Grid grid = VisualHelper.FindVisualChildByName<Grid>(this.AssociatedObject, "TextBlockContainer"); List<TextBlock> tbs = VisualHelper.FindVisualChildren<TextBlock>(grid); foreach (var tb in tbs) { if (tb.TextWrapping != TextWrapping.NoWrap) return false; totalDesiredWidth += MeasureText(tb).Width + tb.Margin.Left + tb.Margin.Right + tb.Padding.Left + tb.Padding.Right; } return Math.Round(this.AssociatedObject.ActualWidth, 5) < Math.Round(totalDesiredWidth, 5); } // Measures text size of textblock private Size MeasureText(TextBlock tb) { var formattedText = new FormattedText(tb.Text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface(tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch), tb.FontSize, Brushes.Black); return new Size(formattedText.Width, formattedText.Height); } } } 

VisualHelper:

 public static class VisualHelper { public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject { T child = null; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { var o = VisualTreeHelper.GetChild(obj, i); if (o != null) { child = o as T; if (child != null) break; else { child = FindVisualChild<T>(o); // recursive if (child != null) break; } } } return child; } public static List<T> FindVisualChildren<T>(DependencyObject obj) where T : DependencyObject { List<T> children = new List<T>(); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { var o = VisualTreeHelper.GetChild(obj, i); if (o != null) { if (o is T) children.Add((T)o); children.AddRange(FindVisualChildren<T>(o)); // recursive } } return children; } public static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : FrameworkElement { T child = default(T); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var o = VisualTreeHelper.GetChild(parent, i); if (o != null) { child = o as T; if (child != null && child.Name == name) break; else child = FindVisualChildByName<T>(o, name); if (child != null) break; } } return child; } } 

您可以在ViewBox中使用隐藏的ItemsControl。

 <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Viewbox VerticalAlignment="Bottom"> <Grid> <TextBlock Text="SomeLongText"/> <ItemsControl Visibility="Hidden"> <ItemsPanelTemplate> <Grid/> </ItemsPanelTemplate> <TextBlock Text="SomeLongText"/> <TextBlock Text="TextA"/> <TextBlock Text="TextB"/> </ItemsControl> </Grid> </Viewbox> <Viewbox Grid.Column="1" VerticalAlignment="Bottom"> <Grid> <TextBlock Text="TextA"/> <ItemsControl Visibility="Hidden"> <ItemsPanelTemplate> <Grid/> </ItemsPanelTemplate> <TextBlock Text="SomeLongText"/> <TextBlock Text="TextA"/> <TextBlock Text="TextB"/> </ItemsControl> </Grid> </Viewbox> <Viewbox Grid.Column="2" VerticalAlignment="Bottom"> <Grid> <TextBlock Text="TextB"/> <ItemsControl Visibility="Hidden"> <ItemsPanelTemplate> <Grid/> </ItemsPanelTemplate> <TextBlock Text="SomeLongText"/> <TextBlock Text="TextA"/> <TextBlock Text="TextB"/> </ItemsControl> </Grid> </Viewbox> </Grid> 

要么

 <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Viewbox VerticalAlignment="Bottom"> <Grid> <TextBlock Text="{Binding Text1}"/> <ItemsControl Visibility="Hidden" ItemsSource="{Binding AllText}"> <ItemsPanelTemplate> <Grid/> </ItemsPanelTemplate> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Viewbox> <Viewbox Grid.Column="1" VerticalAlignment="Bottom"> <Grid> <TextBlock Text="{Binding Text2}"/> <ItemsControl Visibility="Hidden" ItemsSource="{Binding AllText}"> <ItemsPanelTemplate> <Grid/> </ItemsPanelTemplate> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Viewbox> <Viewbox Grid.Column="2" VerticalAlignment="Bottom"> <Grid> <TextBlock Text="{Binding Text3}"/> <ItemsControl Visibility="Hidden" ItemsSource="{Binding AllText}"> <ItemsPanelTemplate> <Grid/> </ItemsPanelTemplate> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Viewbox> </Grid> 

解决scheme可能是这样的:

select一个maxFontSize,然后通过使用线性方程来定义考虑当前窗口显示的合适的FontSize。 窗口的高度或宽度将限制最终的FontSizeselect。

我们来看看整个网格中的“单类TextBlock”的情况:

 Window.Current.SizeChanged += (sender, args) => { int minFontSize = a; int maxFontSize = b; int maxMinFontSizeDiff = maxFontSize - minFontSize; int gridMinHeight = c; int gridMaxHeight = d; int gridMaxMinHeightDiff = gridMaxHeight - gridMinHeight; int gridMinWidth = e; int gridMaxWidth = f; int gridMaxMinHeightDiff = gridMaxWidth - gridMaxWidth; //Linear equation considering "max/min FontSize" and "max/min GridHeight/GridWidth" double heightFontSizeDouble = (maxMinFontSizeDiff / gridMaxMinHeightDiff ) * Grid.ActualHeight + (maxFontSize - (gridMaxHeight * (maxMinFontSizeDiff / gridMaxMinHeightDiff))) double widthFontSizeDouble = (maxMinFontSizeDiff / gridMaxMinWidthDiff ) * Grid.ActualWidth + (maxFontSize - (gridMaxWidth * (maxMinFontSizeDiff / gridMaxMinWidthDiff))) int heightFontSize = (int)Math.Round(heightFontSizeDouble) int widthFontSize = (int)Math.Round(widthFontSizeDouble) foreach (var children in Grid.Children) { (children as TextBlock).FontSize = Math.Min(heightFontSize, widthFontSize); } }