bestsource

TextBlock에서 실행 사이의 공백을 제거하는 방법

bestsource 2023. 4. 9. 21:47
반응형

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>는 텍스트의 텍스트 속성을 대상으로 합니다.실행 사이의 공백이 표시되는 효과를 유발합니다.이렇게 줄일 수도 있습니다.

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

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

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

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

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

연속된 모든 공간이 삭제되고 하나의 공간으로 대체됩니다.

또 다른 옵션은 실행 태그 사이의 공간에 주석을 달아 코드를 판독 가능한 상태로 유지하고 여분의 공간을 제거하는 것입니다.

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

케빈의 멋진 해결책의 한 가지 문제는 한 줄 포맷이XAML일부 XAML/XML 자동 재포맷 기능을 적용하면 태그가 취소됩니다(예: "ctrl-K + ctrl-D").제가 찾은 회피책 중 하나는,Run태그는 다음과 같습니다.

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

이와 같이 태그를 여러 줄로 분할하는 것은 다소 어색하지만, 이 포맷은 자동 재포맷에 의해 변경되지 않습니다.단,Visual StudioXAML 텍스트 편집기의 "속성 사이에 새 줄과 공백 저장" 옵션:

XAML에서 연속 실행 요소 간에 제거된 추가 공간

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

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에는 이러한 공백이 없습니다.

저의 해결책은 기본 글꼴 크기를 거의 보이지 않게 만드는 것입니다.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>

코드 비하인드로 하는 것이 좋을지도 모릅니다.이전 솔루션을 시도했지만 특정 상황에서는 VS가 조심스럽게 입력된 코드를 포맷했습니다.

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

스크린샷

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

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

반응형