Número máximo de líneas para un Wrap TextBlock


Tengo un TextBlock con el siguiente ajuste:

TextWrapping="Wrap"

Puedo determinar el número máximo de líneas?

Por ejemplo, considere la siguiente cadena TextBlock.Text:

This is a very good horse under the blackboard!!

Actualmente ha habido programas como este:

This is a very 
good horse under 
the blackboard!!

Necesito que eso se convierta en algo como:

This is a very 
good horse ...

Alguna solución?

Author: Mayank, 2012-11-30

7 answers

Actualización (para UWP)

En las aplicaciones UWP no necesita esto y puede usar la propiedad TextBlock MaxLines (ver MSDN)


Respuesta original:

Si tiene un LineHeight específico, puede calcular la altura máxima para el TextBlock.

Ejemplo:

TextBlock con un máximo de 3 líneas

<TextBlock 
  Width="300"
  TextWrapping="Wrap" 
  TextTrimming="WordEllipsis" 
  FontSize="24" 
  LineStackingStrategy="BlockLineHeight"
  LineHeight="28"
  MaxHeight="84">YOUR TEXT</TextBlock>

Esto es todo lo que necesita para que su requisito funcione.

¿Cómo hacer esto dinámicamente?

Solo crear un nuevo control en C#/VB.NET que extienda TextBlock y darle un nuevo DependencyProperty int maxLines .
Luego sobrescribe el método OnApplyTemplate() y establece el MaxHeight basado en el LineHeight * MaxLines.

¡Eso es solo una explicación básica sobre cómo puedes resolver este problema!

 43
Author: tobi.at,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-18 12:50:34

Si tiene Height, TextWrapping, y TextTrimming todo listo, se comportará exactamente como quieres:

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

El código anterior envolverá hasta dos líneas, luego use CharacterEllipsis más allá de ese punto.

 3
Author: Greg Lary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-21 19:38:51

Necesita TextTrimming="WordEllipsis" ajuste en su TextBlock

 2
Author: Mayank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-30 02:09:45

Basado tobi.at he creado este comportamiento MaxLines. Fundamentalmente, no depende de establecer la propiedad LineHeight calculando la altura de la línea a partir de la fuente. Todavía necesita establecer TextWrapping y TextTrimming para que el TextBox se procese como desee.

<TextBlock behaviours:NumLinesBehaviour.MaxLines="3" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" Text="Some text here"/>

También hay un comportamiento MinLines que puede ser diferente o establecer el mismo número que el comportamiento MaxLines para establecer el número de líneas.

public class NumLinesBehaviour : Behavior<TextBlock>
{
    TextBlock textBlock => AssociatedObject;

    protected override void OnAttached()
    {
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
    }

    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;
    }
}
 1
Author: Itzalive,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-31 11:43:07

Basado en la respuesta de @artistandsocial, creé una propiedad adjunta para establecer el número máximo de líneas programáticamente (en lugar de tener que sobrecargar TextBlock que se desaconseja en 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(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)
    {
        var element = d as TextBlock;
        if (element != null)
        {
            element.MaxHeight = element.LineHeight * GetMaxLines(element);
        }
    }
}

De forma predeterminada, el LineHeight se establece en double.NaN, por lo que este valor debe establecerse primero manualmente.

La propiedad adjunta MaxLines y otras propiedades relevantes se pueden establecer en un 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>
 0
Author: g t,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-15 12:45:55

Para cualquiera que desarrolle aplicaciones UWP o WinRT, TextBlock tiene un MaxLines propiedad que puede establecer.

 0
Author: Francisco Aguilera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-01 22:00:26

Dudo que sea configurable, el ajuste se basa en una serie de factores como el tamaño de fuente/kerning, el ancho disponible del bloque de texto (horizontalalignment=stretch puede hacer una gran diferencia), el tipo de panel del padre (scrollviewer/stackpanel/grid), etc.

Si desea que el texto fluya a la siguiente línea explícitamente, debe usar bloques "Run" en su lugar y luego usar wrapping de elipses de tipo para ese bloque run.

 -3
Author: Rohit Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-30 02:12:22