xaml - microsoft - uwp vs wpf
Número máximo de líneas para un Wrap TextBlock (7)
Basado en la respuesta de @ artistandsocial, creé una propiedad adjunta para establecer la cantidad máxima de líneas programáticamente (en lugar de tener que sobrecargar TextBlock
cual 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, LineHeight
está configurado en double.NaN
, por lo que este valor primero debe establecerse 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>
Tengo un TextBlock
con la siguiente configuración:
TextWrapping="Wrap"
¿Puedo determinar la cantidad máxima de líneas?
por ejemplo, considere la siguiente cadena TextBlock.Text
:
This is a very good horse under the blackboard!!
Actualmente ha habido shows como este:
This is a very
good horse under
the blackboard!!
Necesito que se convierta en algo así como:
This is a very
good horse ...
¿alguna solución?
Basado en la respuesta debi.at y gt, he creado este comportamiento de MaxLines
. Fundamentalmente, no depende de establecer la propiedad LineHeight
calculando el alto de la línea desde la fuente. Aún necesita configurar TextWrapping
y TextTrimming
para que el TextBox
se TextTrimming
como lo desea.
<TextBlock behaviours:NumLinesBehaviour.MaxLines="3" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" Text="Some text here"/>
También hay un comportamiento MinLines
que puede ser diferente o establecerse en el mismo número que el comportamiento de 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;
}
}
Dudo que sea configurable, el empaquetado se basa en una serie de factores como tamaño de letra / interletraje, ancho disponible del bloque de texto (horizontalalignment = stretch puede hacer una gran diferencia), tipo de panel principal (scrollviewer / stackpanel / grid) etc.
Si desea que el texto fluya a la siguiente línea explícitamente, debe usar bloques "Ejecutar" en su lugar y luego usar el ajuste de las elipses de tipo para ese bloque de ejecución.
Para cualquiera que esté desarrollando aplicaciones UWP o WinRT, TextBlock
tiene una propiedad MaxLines
que puede configurar.
Si tiene TextWrapping
Height
, TextWrapping
y TextTrimming
, se comportará exactamente como lo desee:
<TextBlock Height="60" FontSize="22" FontWeight="Thin"
TextWrapping="Wrap" TextTrimming="CharacterEllipsis">
El código anterior se ajustará a dos líneas, luego usar CharacterEllipsis
más allá de ese punto.
Si tiene un LineHeight
específico, puede calcular la altura máxima para 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 requerimiento funcione.
¿Cómo hacer esto dinámicamente?
Simplemente cree un nuevo control en C # / VB.NET que extienda TextBlock
y le otorgue un nuevo DependencyProperty
int MaxLines .
A continuación, anule el método OnApplyTemplate()
y establezca MaxHeight
basado en LineHeight
* MaxLines
.
¡Esa es solo una explicación básica de cómo puedes resolver este problema!
Actualización (para UWP)
En UWP Apps no es necesario y puede utilizar la propiedad TextBlock MaxLines
(ver MSDN )
necesita la TextTrimming="WordEllipsis"
en su TextBlock