WPF中TextBlock设WrapWithOverflow后滚动条提前显示问题
这个问题我之前也碰到过,确实是DockPanel的Margin导致的——你直接把TextBlock的Width绑定到ScrollViewer的ActualWidth,但没考虑到ScrollViewer内部的DockPanel有左右各5的Margin,这就导致TextBlock的宽度被设成了ScrollViewer的总宽度,而它实际能使用的空间其实是总宽度减去10(Margin的左右总和),所以还没等按钮被截断,TextBlock就超出了可用空间,触发了滚动条。
给你两个解决方案,选最适合你的:
方案一:移除Width绑定(推荐)
最简单的修复就是删掉TextBlock的Width绑定,让它自动继承父容器的可用宽度。因为DockPanel默认会让最后一个子元素填充剩余空间,这样TextBlock会自动适配扣除Margin后的空间,只有当顶部的按钮栏宽度超过ScrollViewer时,才会出现水平滚动条,完全符合你的预期。
修正后的XAML:
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <DockPanel Margin="5"> <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> <Button Content="First Button" Margin="0,0,10,0"/> <Button Content="Second Button"/> </StackPanel> <TextBlock VerticalAlignment="Center" IsHitTestVisible="False" TextAlignment="Center" TextWrapping="WrapWithOverflow" MaxWidth="260"> Just a small line<LineBreak /> This is the long line which will wrap during resize </TextBlock> </DockPanel> </ScrollViewer>
方案二:使用绑定转换器(如果必须保留Width绑定)
如果因为特殊布局需求,你一定要保留Width绑定,那可以用一个绑定转换器来扣除Margin的数值:
先创建转换器类:
public class SubtractValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is double actualWidth && double.TryParse(parameter?.ToString(), out double subtractValue)) { return actualWidth - subtractValue; } return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
然后在XAML中引用并使用:
<Window.Resources> <local:SubtractValueConverter x:Key="SubtractValueConverter"/> </Window.Resources> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <DockPanel Margin="5"> <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> <Button Content="First Button" Margin="0,0,10,0"/> <Button Content="Second Button"/> </StackPanel> <DockPanel> <TextBlock VerticalAlignment="Center" IsHitTestVisible="False" TextAlignment="Center" TextWrapping="WrapWithOverflow" Width="{Binding RelativeSource={RelativeSource AncestorType=ScrollViewer}, Path=ActualWidth, Converter={StaticResource SubtractValueConverter}, ConverterParameter=10}" MaxWidth="260"> Just a small line<LineBreak /> This is the long line which will wrap during resize </TextBlock> </DockPanel> </DockPanel> </ScrollViewer>
这里ConverterParameter=10对应DockPanel左右Margin的总和(5+5),这样TextBlock的宽度就刚好匹配ScrollViewer内部的可用空间了。
内容的提问来源于stack exchange,提问作者Franz Gsell
相关产品推荐
相关产品推荐

