c# - samples - RichTextBlock sigue insertando espacios entre ejecuciones en UWP
uwp samples (3)
Tengo este muy simple RichtTextBlock
:
<RichTextBlock VerticalAlignment="Center">
<Paragraph>
<Run Text="Hello" />
<Run Text="world" />
</Paragraph>
</RichTextBlock>
En tiempo de diseño, las ejecuciones aparecen sin espacio entre ellas (¡ eso es lo que necesito! ), Pero en el tiempo de ejecución, ambas carreras están separadas por un espacio.
Para ilustrar el problema, aquí están las instantáneas:
En el diseñador de Visual Studio, así se representa:
Eso para mí es el comportamiento correcto.
Sin embargo, en tiempo de ejecución, se representa así:
¿Cómo hago que Runs se una en conjunto en lugar de espaciarse?
¡Pieter Nijs ha creado una propiedad adjunta para arreglar esto! Los detalles están en su blog aquí ...
En resumen, obtendrá todo el texto disponible de las ejecuciones y eliminará los espacios que encuentre antes de expulsar el texto.
var spaces = tb.Inlines.Where(a => a is Run
&& ((Run)a).Text == " "
&& !GetPreserveSpace(a)).ToList();
spaces.ForEach(s => tb.Inlines.Remove(s));
De acuerdo, después de leer la publicación de Pieter Nijs, he creado un Comportamiento para UWP que funciona para las aplicaciones de Universal de Windows.
public class RemoveEmptyRunsBehavior : Behavior<RichTextBlock>
{
protected override void OnAttached()
{
RemoveWhitespaceRuns(this.AssociatedObject);
}
private void RemoveWhitespaceRuns(RichTextBlock tb)
{
var tuples = from p in tb.Blocks.OfType<Paragraph>()
from r in p.Inlines.OfType<Run>()
where r.Text == " "
select new { Paragraph = p, Run = r };
foreach (var tuple in tuples)
{
tuple.Paragraph.Inlines.Remove(tuple.Run);
}
}
}
El uso es muy simple: conéctelo al RichTextBlock para que elimine los espacios adicionales.
<RichTextBlock VerticalAlignment="Center">
<Paragraph>
<Run Text="Hello" />
<Run Text="world" />
</Paragraph>
<interactivity:Interaction.Behaviors>
<local:RemoveEmptyRunsBehavior />
</interactivity:Interaction.Behaviors>
</RichTextBlock>
No olvide agregar los comportamientos XAML para UWP (de NuGet): Microsoft.Xaml.Behaviors.Uwp.Managed
y para agregar esta declaración de prefijo de espacio de nombres!
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
Genial, no sabía que, como dijo Glenn, habría tanta diferencia entre TextBlock
y Rich
sophew ;-).
Actualicé mi código para trabajar con RichTextBlock
(podría necesitar algunos ajustes adicionales, pero parece funcionar en el escenario proporcionado).
public class RichTextBlockExtension
{
public static bool GetRemoveEmptyRuns(DependencyObject obj)
{
return (bool)obj.GetValue(RemoveEmptyRunsProperty);
}
public static void SetRemoveEmptyRuns(DependencyObject obj, bool value)
{
obj.SetValue(RemoveEmptyRunsProperty, value);
if (value)
{
var tb = obj as RichTextBlock;
if (tb != null)
{
tb.Loaded += Tb_Loaded;
}
else
{
throw new NotSupportedException();
}
}
}
public static readonly DependencyProperty RemoveEmptyRunsProperty =
DependencyProperty.RegisterAttached("RemoveEmptyRuns", typeof(bool),
typeof(RichTextBlock), new PropertyMetadata(false));
public static bool GetPreserveSpace(DependencyObject obj)
{
return (bool)obj.GetValue(PreserveSpaceProperty);
}
public static void SetPreserveSpace(DependencyObject obj, bool value)
{
obj.SetValue(PreserveSpaceProperty, value);
}
public static readonly DependencyProperty PreserveSpaceProperty =
DependencyProperty.RegisterAttached("PreserveSpace", typeof(bool),
typeof(Run), new PropertyMetadata(false));
private static void Tb_Loaded(object sender, RoutedEventArgs e)
{
var tb = sender as RichTextBlock;
tb.Loaded -= Tb_Loaded;
foreach (var item in tb.Blocks)
{
Paragraph p = item as Paragraph;
if(p!=null)
{
var spaces = p.Inlines.Where(a => a is Run
&& ((Run)a).Text == " "
&& !GetPreserveSpace(a)).ToList();
spaces.ForEach(s => p.Inlines.Remove(s));
}
}
}
}