Nice programing

TextBlock에서 실행 사이의 공백을 제거하는 방법은 무엇입니까?

nicepro 2020. 12. 26. 16:34
반응형

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합니까?


실행 태그 사이의 공백으로 인해 공백이 발생합니다. 이것이 가장 쉬운 해결 방법입니다.

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

<TextBlock>사이의 모든 것이 </TextBlock>TextBlock의 text 속성을 대상으로 하기 때문에 실행 사이의 공백으로 인해 나타나는 효과가 발생합니다. 이것으로 줄일 수도 있습니다.

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

이 MSDN 기사는 xaml이 공백을 처리하는 방법에 대한 모든 세부 사항을 제공합니다.

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

휴식 시간과 수많은 탭이 하나의 공간으로 변환되는 이유가 궁금하다면

모든 공백 문자 (공백, 줄 바꿈, 탭)는 공백으로 변환됩니다.

연속 된 모든 공백이 삭제되고 하나의 공백으로 바뀝니다.


또 다른 옵션은 Run 태그 사이의 공백을 주석 처리하여 코드를 읽을 수 있도록 유지하고 추가 공백을 제거하는 것입니다.

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

Kevin의 멋진 솔루션의 한 가지 문제점 XAML은 "ctrl-K + ctrl-D"와 같은 일부 XAML / XML 자동 서식 변경 기능 을 적용 할 때 태그 의 한 줄 서식 이 취소된다는 것입니다. 내가 찾은 한 가지 해결 방법 Run은 다음과 같이 태그 형식을 지정하는 것입니다.

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

이와 같이 태그를 여러 줄로 분할하는 것은 다소 어색 Visual Studio하지만 XAML 텍스트 편집기에 대해 "속성 사이에 새 줄과 공백 유지"옵션 을 선택하면이 형식은 자동 서식 재 지정으로 변경되지 않습니다 .

XAML의 연속 Run 요소 사이에 추가 공간이 제거되었습니다.


이 동작을 '우회'하기 위해 연결된 속성을 작성했습니다.

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));
    }
}

The entire source code and the explanation of it all can be found here. By using this attached property you can keep your XAML formatting just the way you want, but you don't get these whitespaces in your rendered XAML.


My solution is to make the default font size nearly invisible(FontSize="1") and then set the font size to the desired size at every each <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>

You may be better off doing it in Code Behind. I have tried previous solutions but in certain situations VS just formatted away the carefully indented code.


I ported Pieter's attached property to WPF (I think it's for UWP).

Example:

<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>

스크린 샷

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;
    }
}

ReferenceURL : https://stackoverflow.com/questions/11090084/how-to-get-rid-of-whitespace-between-runs-in-textblock

반응형