我在WPF的网格中有一些文本块,我想根据它们的可用宽度/高度进行缩放。当我搜索自动缩放字体大小时,典型的建议是将文本块放入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的字体。但是,这看起来很有趣,因为如果其中一个TextBlock的文本较长,那么它的字体会较小,而它的相邻网格元素的字体会较大。我希望字体大小按组缩放,如果我能为一组控件指定“SharedSizeGroup”来自动调整字体大小,也许会更好。
例如:
第一个文本块的文本可能是“3/26/2013 10:45:30 AM”,第二个文本块的文本可能是“FileName.ext”。如果这些文本块横跨窗口的宽度,并且用户开始将窗口的大小调整得越来越小。日期将开始使其字体小于文件名,具体取决于文件名的长度。
理想情况下,一旦其中一个文本字段开始调整字体点大小,它们都将匹配。有人想出了一个解决方案,或者可以给予我一个机会,你会如何使它工作?如果它需要自定义代码,那么希望我们/我可以重新打包到一个自定义混合或附加行为,以便在未来可重用。我认为这是一个相当普遍的问题,但我找了半天也没找到。
更新我尝试了Mathieu的建议,它有点工作,但它有一些副作用:
<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>
在这里,我希望限制字体的大小,这样就不会浪费垂直窗口真实的。我希望输出左对齐、居中对齐、右对齐,字体尽可能大,直到达到所需的最大大小。
@阿达比龙
您提出的解决方案不错(也是目前最好的),但它确实有一些局限性。例如,最初我希望我的列是成比例的(第二列应该居中)。例如,我的TextBlock可能会标记图表的开始、中心和结束,而对齐方式很重要。
<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时,看起来网格默认为“自动”列大小,不再居中对齐。
7条答案
按热度按时间fkvaft9z1#
我想修改我已经提供的答案,但后来决定发布一个新的答案更有意义,因为这真的取决于我更喜欢哪一个。这里的答案可能更符合Alan的想法,因为
(第一次)
other one的优势在于
我还在StackPanel/DockPanel类型的顶部容器中测试了此解决方案,表现良好。
请注意,通过调整列/行的宽度/高度(自动调整/星形调整),您可以获得不同的行为。因此,也可以将所有三个文本块列都设置为星形调整,但这意味着宽度裁剪确实会更早发生,并且有更多的边距。或者,如果网格所在的行是自动调整的,则高度裁剪永远不会发生。
XAML:
缩放字体行为:
可视化助手:
fdx2calv2#
将网格放在ViewBox中,这将缩放整个网格:
mwecs4sa3#
我想我知道该怎么做,剩下的就交给你了。在这个例子中,我使用一个转换器(转换器如下所示)将FontSize绑定到TextBlock的ActualHeight:
ddarikpa4#
一般备注:整个文本缩放的一个可能的替代方法是只对TextBlocks使用TextTrimming。
我一直在努力寻找解决这个问题的方法。使用视图框很难与任何布局调整相结合。最糟糕的是,ActualWidth等参数在视图框中不会改变。所以我最终决定只有在绝对必要的时候才使用视图框,也就是剪辑发生的时候。因此,我在ContentPresenter和Viewbox之间移动内容,这取决于可用的空间。
这个解决方案并不像我所希望的那样通用,主要是MoveToViewboxBehavior确实假设它附加到具有以下结构的网格。如果不能满足这一点,则很可能必须调整行为。创建一个用户控件并表示必要的部分(PART_...)可能是一个有效的替代方案。
注意,我已经将网格的列从3列扩展到了5列,因为这使得解决方案变得容易得多。这意味着中间的文本块将不会精确地位于中间,在绝对坐标的意义上,而是位于左右文本块的中间。
xriantvc5#
您可以在ViewBox中使用隐藏的ItemsControl。
或
6rqinv9w6#
解决方案可能是这样的:
选择maxFontSize,然后使用线性方程根据当前窗口定义要显示的相应FontSize。窗口的高度或宽度将限制最终的FontSize选择。
让我们以整个网格的“单一类型TextBlock”为例:
twh00eeo7#
我使用
ScaleTransform
。这将按所需的量缩放当前字体:ScaleX
和ScaleY
越大,字体的缩放比例就越大。无需更改单个字体大小。它也可以仅与
ScaleX
或ScaleY
一起使用,以仅在一个方向上更改字体大小,或使用不同的值。使用方法:
...给出:
还有:
...给出: