Wrap TextBlock 的最大行数
Posted
技术标签:
【中文标题】Wrap TextBlock 的最大行数【英文标题】:Maximum number of lines for a Wrap TextBlock 【发布时间】:2012-11-18 05:40:59 【问题描述】:我有一个TextBlock
,其设置如下:
TextWrapping="Wrap"
我可以确定最大行数吗?
例如考虑以下字符串TextBlock.Text
:
This is a very good horse under the blackboard!!
目前有这样的节目:
This is a very
good horse under
the blackboard!!
我需要它变成这样:
This is a very
good horse ...
有什么办法吗?
【问题讨论】:
【参考方案1】:您需要在TextBlock
中设置TextTrimming="WordEllipsis"
【讨论】:
谢谢,但这仅在文本到达TextBlock
的末尾时才有效,这可能是 2 行或更多行。我希望TextBlock
在例如之后修剪文本正好 2 行。
@MBZ 为此,您需要编写自定义转换器,该转换器会遍历您的 TextBlock
文本并在需要的地方插入省略号。
如果你可以设置文本块的高度,修剪和环绕设置应该是你所需要的全部【参考方案2】:
我怀疑这是可配置的,换行基于许多因素,例如字体大小/字距调整、文本块的可用宽度(horizontalalignment=stretch 可以产生很大的不同)、父面板类型(scrollviewer/stackpanel/grid ) 等。
如果您希望文本明确地流到下一行,您应该使用“运行”块,然后对该运行块使用类型省略号的换行。
【讨论】:
请看下面@kindasimple 的评论,这会给你想要的。 为什么选择这个作为答案?【参考方案3】:更新(针对 UWP)
在 UWP 应用中你不需要这个并且可以使用 TextBlock 属性MaxLines
(参见MSDN)
原答案:
如果您有特定的LineHeight
,您可以计算 TextBlock 的最大高度。
示例:
最多 3 行的文本块
<TextBlock
Width="300"
TextWrapping="Wrap"
TextTrimming="WordEllipsis"
FontSize="24"
LineStackingStrategy="BlockLineHeight"
LineHeight="28"
MaxHeight="84">YOUR TEXT</TextBlock>
这就是满足您的要求所需要的一切。
如何动态地做到这一点?
只需在 C#/VB.NET 中创建一个扩展 TextBlock
的新控件,并为其赋予一个新的 DependencyProperty
int MaxLines。
然后重写OnApplyTemplate()
方法,并根据LineHeight
* MaxLines
设置MaxHeight
。
这只是关于如何解决这个问题的基本解释!
【讨论】:
【参考方案4】:如果您已设置好 Height
、TextWrapping
和 TextTrimming
,它将完全按照您的意愿行事:
<TextBlock Height="60" FontSize="22" FontWeight="Thin"
TextWrapping="Wrap" TextTrimming="CharacterEllipsis">
上面的代码最多会换行两行,然后在此之后使用CharacterEllipsis
。
【讨论】:
【参考方案5】:根据@artistandsocial 的回答,我创建了一个附加属性来以编程方式设置最大行数(而不是在 WPF 中不鼓励重载 TextBlock
)。
public class LineHeightBehavior
public static readonly DependencyProperty MaxLinesProperty =
DependencyProperty.RegisterAttached(
"MaxLines",
typeof(int),
typeof(LineHeightBehavior),
new PropertyMetadata(default(int), OnMaxLinesPropertyChangedCallback));
public static void SetMaxLines(TextBlock element, int value) => element.SetValue(MaxLinesProperty, value);
public static int GetMaxLines(TextBlock element) =>(int)element.GetValue(MaxLinesProperty);
private static void OnMaxLinesPropertyChangedCallback(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
if (d is TextBlock textBlock)
if (textBlock.IsLoaded)
SetLineHeight();
else
textBlock.Loaded += OnLoaded;
void OnLoaded(object _, RoutedEventArgs __)
textBlock.Loaded -= OnLoaded;
SetLineHeight();
void SetLineHeight()
double lineHeight =
double.IsNaN(textBlock.LineHeight)
? textBlock.FontFamily.LineSpacing * textBlock.FontSize
: textBlock.LineHeight;
textBlock.MaxHeight = Math.Ceiling(lineHeight * GetMaxLines(textBlock));
默认情况下LineHeight
设置为double.NaN
,所以这个值必须先手动设置,否则根据TextBlock
的FontFamily
和FontSize
计算高度。
然后可以在Style
中设置附加属性MaxLines
和其他相关属性:
<Style TargetType="x:Type TextBlock"
BasedOn="StaticResource x:Type TextBlock">
<Setter Property="TextTrimming"
Value="CharacterEllipsis" />
<Setter Property="TextWrapping"
Value="Wrap" />
<Setter Property="LineHeight"
Value="16" />
<Setter Property="LineStackingStrategy"
Value="BlockLineHeight" />
<Setter Property="behaviors:LineHeightBehavior.MaxLines"
Value="2" />
</Style>
【讨论】:
【参考方案6】:对于开发 UWP 或 WinRT 应用程序的任何人,TextBlock
具有您可以设置的 MaxLines
属性。
【讨论】:
【参考方案7】:基于 tobi.at 和 gt 的回答,我创建了这个 MaxLines
行为。至关重要的是,它不依赖于通过计算字体的行高来设置LineHeight
属性。您仍然需要设置 TextWrapping
和 TextTrimming
以使其 TextBox
可以根据需要进行渲染。
<TextBlock behaviours:NumLinesBehaviour.MaxLines="3" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" Text="Some text here"/>
还有一个MinLines
行为,它可以与MaxLines
行为不同或设置为相同的数字来设置行数。
public class NumLinesBehaviour : Behavior<TextBlock>
TextBlock textBlock => AssociatedObject;
public static readonly DependencyProperty MaxLinesProperty =
DependencyProperty.RegisterAttached(
"MaxLines",
typeof(int),
typeof(NumLinesBehaviour),
new PropertyMetadata(default(int), OnMaxLinesPropertyChangedCallback));
public static void SetMaxLines(DependencyObject element, int value)
element.SetValue(MaxLinesProperty, value);
public static int GetMaxLines(DependencyObject element)
return (int)element.GetValue(MaxLinesProperty);
private static void OnMaxLinesPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
TextBlock element = d as TextBlock;
element.MaxHeight = getLineHeight(element) * GetMaxLines(element);
public static readonly DependencyProperty MinLinesProperty =
DependencyProperty.RegisterAttached(
"MinLines",
typeof(int),
typeof(NumLinesBehaviour),
new PropertyMetadata(default(int), OnMinLinesPropertyChangedCallback));
public static void SetMinLines(DependencyObject element, int value)
element.SetValue(MinLinesProperty, value);
public static int GetMinLines(DependencyObject element)
return (int)element.GetValue(MinLinesProperty);
private static void OnMinLinesPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
TextBlock element = d as TextBlock;
element.MinHeight = getLineHeight(element) * GetMinLines(element);
private static double getLineHeight(TextBlock textBlock)
double lineHeight = textBlock.LineHeight;
if (double.IsNaN(lineHeight))
lineHeight = Math.Ceiling(textBlock.FontSize * textBlock.FontFamily.LineSpacing);
return lineHeight;
【讨论】:
在删除了不必要的东西后,比如“: Behavior以上是关于Wrap TextBlock 的最大行数的主要内容,如果未能解决你的问题,请参考以下文章
Windows 8.1 应用程序:使用换行、最大行数或最大高度识别 TextBlock 的 UI 文本截断
Windows 8 ScrollViewer 打破 TextBlock Wrap