Подтвердить что ты не робот

Как избавиться от пробелов между Runs in TextBlock?

У меня есть XAML:

<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
                                               FontSize="10" FontFamily="Arial" Foreground="#414141">        
                                            <Run Text="{Binding LoadsCount}" />        
                                            <Run Text="+" />        
                                            <Run Text="{Binding BrokerLoadsCount}" />
                                        </TextBlock>

И я получаю отображение следующим образом: 12 + 11 Каким-то образом он вставляет дополнительное пространство между каждым Run Как мне отобразить 12+11?

4b9b3361

Ответ 1

Пробелы между тегами запуска вызывают пробелы, это самое простое исправление.

<TextBlock 
   HorizontalAlignment="Center" 
   VerticalAlignment="Center"
   FontSize="10" 
   FontFamily="Arial" 
   Foreground="#414141">        
      <Run Text="{Binding LoadsCount}" /><Run Text="+" /><Run Text="{Binding BrokerLoadsCount}" />
</TextBlock>

Поскольку все, что находится между <TextBlock> и </TextBlock>, нацелено на свойство text TextBlock, пробелы из разрывов между прогонами приводят к эффекту, который вы видите. Вы также можете сократить его до этого.

<Run Text="{Binding LoadsCount}" />+<Run Text="{Binding BrokerLoadsCount}" />

В этой статье MSDN приведены все сведения о том, как xaml обрабатывает пробелы

http://msdn.microsoft.com/en-us/library/ms788746.aspx

Если вам было любопытно, почему перерыв и тонна вкладок переводятся в одно пространство

Все пробельные символы (пробел, строка, вкладка) преобразуются в пространства.

Все последовательные пробелы удаляются и заменяются одним пробелом

Ответ 2

Одна из проблем с хорошим решением Kevin заключается в том, что однострочное форматирование тегов XAML отменяется, когда вы применяете некоторые функции автоматического переформатирования XAML/XML, например. "ctrl-K + ctrl-D". Обходным решением, которое я нашел, является форматирование тегов Run следующим образом:

<TextBlock>
    <Run FontStyle="Italic"
    Text="aaa" /><Run 
    Text="bbb" />
</TextBlock>

Хотя разделение тега на строки, подобные этому, несколько неудобно, этот формат не будет изменен путем автоматического переформатирования, если вы выберете опцию Visual Studio "Сохраните новые строки и пробелы между атрибутами" для текстового редактора XAML:

extra space eliminated between consecutive Run elements in XAML

Ответ 3

Другой вариант - прокомментировать пробел между тегами запуска, сохранением прочитанного кода и удалением лишнего места.

<TextBlock HorizontalAlignment="Center"
           VerticalAlignment="Center"
           FontSize="10" FontFamily="Arial" Foreground="#414141">        
    <Run Text="{Binding LoadsCount}" /><!--
 --><Run Text="+" /><!--
 --><Run Text="{Binding BrokerLoadsCount}" />
</TextBlock>

Ответ 4

Я написал Attached Property, чтобы "обходить" это поведение.

public class TextBlockExtension
{

    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 TextBlock;
            if (tb != null)
            {
                tb.Loaded += Tb_Loaded;
            }
            else
            {
                throw new NotSupportedException();
            }
        }
    }

    public static readonly DependencyProperty RemoveEmptyRunsProperty =
        DependencyProperty.RegisterAttached("RemoveEmptyRuns", typeof(bool), 
            typeof(TextBlock), 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 TextBlock;
        tb.Loaded -= Tb_Loaded;

       var spaces = tb.Inlines.Where(a => a is Run 
            && string.IsNullOrWhiteSpace(((Run)a).Text) 
            && !GetPreserveSpace(a)).ToList();
        spaces.ForEach(s => tb.Inlines.Remove(s));
    }
}

Весь исходный код и объяснение всего этого можно найти здесь. Используя это прикрепленное свойство, вы можете сохранить форматирование XAML так, как вы хотите, но вы не получите эти пробелы в визуализированном XAML.

Ответ 5

Мое решение состоит в том, чтобы сделать размер шрифта по умолчанию почти невидимым (FontSize="1"), а затем установить размер шрифта на требуемый размер в каждом из <Run:

<TextBlock HorizontalAlignment="Center"
           VerticalAlignment="Center"
           FontSize="1"
           FontFamily="Arial"
           Foreground="#414141">        

    <Run FontSize="10" Text="{Binding LoadsCount}" />        
    <Run FontSize="10" Text="+" />        
    <Run FontSize="10" Text="{Binding BrokerLoadsCount}" />
</TextBlock>

Возможно, вам лучше сделать это в Code Behind. Я пробовал предыдущие решения, но в некоторых ситуациях VS просто отформатировал тщательно отпечатанный код.

Ответ 6

Я поместил приложение Pieter в WPF (я думаю, это для UWP).

Пример:

<StackPanel>
    <TextBlock Text="Before:" FontWeight="SemiBold"/>
    <TextBlock>
        Foo
        <Run Text="Bar"/>
        <Run>Baz</Run>
    </TextBlock>
    <TextBlock Text="After:" FontWeight="SemiBold" Margin="0,10,0,0"/>
    <TextBlock local:TextBlockHelper.TrimRuns="True">
        Foo
        <Run Text="Bar"/>
        <Run>Baz</Run>
    </TextBlock>
    <TextBlock Text="Use two spaces if you want one:" FontWeight="SemiBold" Margin="0,10,0,0"/>
    <TextBlock local:TextBlockHelper.TrimRuns="True">
        Foo
        <Run Text="  Bar"/>
        <Run>Baz</Run>
    </TextBlock>
</StackPanel>

screenshot

using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

public class TextBlockHelper
{
    public static bool GetTrimRuns(TextBlock textBlock) => (bool)textBlock.GetValue(TrimRunsProperty);
    public static void SetTrimRuns(TextBlock textBlock, bool value) => textBlock.SetValue(TrimRunsProperty, value);

    public static readonly DependencyProperty TrimRunsProperty =
        DependencyProperty.RegisterAttached("TrimRuns", typeof(bool), typeof(TextBlockHelper),
            new PropertyMetadata(false, OnTrimRunsChanged));

    private static void OnTrimRunsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBlock = d as TextBlock;
        textBlock.Loaded += OnTextBlockLoaded;
    }

    static void OnTextBlockLoaded(object sender, EventArgs args)
    {
        var textBlock = sender as TextBlock;
        textBlock.Loaded -= OnTextBlockLoaded;

        var runs = textBlock.Inlines.OfType<Run>().ToList();
        foreach (var run in runs)
            run.Text = TrimOne(run.Text);
    }

    private static string TrimOne(string text)
    {
        if (text.FirstOrDefault() == ' ')
            text = text.Substring(1);
        if (text.LastOrDefault() == ' ')
            text = text.Substring(0, text.Length - 1);

        return text;
    }
}