31

我有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 ...

任何解决方案?

4

7 回答 7

52

更新(针对 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()方法并设置MaxHeight基于LineHeight* MaxLines

这只是关于如何解决此问题的基本解释!

于 2013-11-19T19:53:09.997 回答
7

根据 tobi.at 和 gt 的回答,我创造了这种MaxLines行为。至关重要的是,它不依赖于LineHeight通过计算字体的行高来设置属性。您仍然需要设置它并根据TextWrapping需要进行渲染。TextTrimmingTextBox

<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;
    }
}
于 2017-03-31T11:43:07.533 回答
5

如果您已设置Height, TextWrapping, 并且TextTrimming全部设置,它将完全按照您的意愿行事:

<TextBlock Height="60" FontSize="22" FontWeight="Thin"
    TextWrapping="Wrap" TextTrimming="CharacterEllipsis">

上面的代码最多包含两行,然后在此之后使用CharacterEllipsis

于 2014-10-21T19:38:51.470 回答
2

你需要TextTrimming="WordEllipsis"在你的TextBlock

于 2012-11-30T02:09:45.257 回答
1

根据@artistandsocial 的回答,我创建了一个附加属性来以编程方式设置最大行数(而不是TextBlock在 WPF 中不鼓励重载)。

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,因此必须先手动设置此值,否则根据FontFamily和计算FontSize高度TextBlock

MaxLines然后可以在 a 中设置附加属性和其他相关属性Style

<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>
于 2016-04-15T12:45:55.590 回答
0

对于开发 UWP 或 WinRT 应用程序的任何人,您都可以设置TextBlock一个MaxLines属性。

于 2017-03-01T22:00:26.290 回答
-4

我怀疑这是可配置的,换行基于许多因素,例如字体大小/字距调整、文本块的可用宽度(horizo​​ntalalignment=stretch 可以产生很大的不同)、父面板类型(scrollviewer/stackpanel/grid)等。

如果您希望文本显式地流到下一行,则应改用“运行”块,然后对该运行块使用椭圆类型的换行。

于 2012-11-30T02:12:22.643 回答