TextBlock,其中一些文本左对齐,其余文本右对齐

Khu*_*shi 7 c# wpf xaml

我想要一个包含以下文本的文本块:

My associated textbox is                :
Run Code Online (Sandbox Code Playgroud)

文本左对齐,冒号右对齐.

我知道如何使用两个文本块获得上述输出.但我想知道适用于单个文本块的行为是否相同?

McG*_*gle 8

TextBlock本质上反对一致的儿童的概念,但当然有一些可能的黑客攻击:

  1. 填充空格以给出对齐的外观.
  2. 用于在TextBlock中InlineUIContainer添加实际的UI元素(可以对齐).

我将通过创建一个ExtendedTextBlock带有LeftAlignedTextRightAlignedText属性的控件给出每个示例.用法是这样的:

<my:ExtendedTextBlock RightAlignedText=":" LeftAlignedText="My associated textbox is" />
Run Code Online (Sandbox Code Playgroud)

1)用空格填充.

对于这种方法,我借用了这个答案来获得文本字符串的实际宽度.这个想法基本上是从控件的实际宽度中减去文本的总宽度,并在它们之间插入适当数量的空格.

public class ExtendedTextBlock : TextBlock
{
    public string RightAlignedText
    {
        get { return (string)GetValue(RightAlignedTextProperty); }
        set { SetValue(RightAlignedTextProperty, value); }
    }
    public static readonly DependencyProperty RightAlignedTextProperty =
        DependencyProperty.Register("RightAlignedText", typeof(string), typeof(ExtendedTextBlock), new PropertyMetadata(SetText));

    public string LeftAlignedText
    {
        get { return (string)GetValue(LeftAlignedTextProperty); }
        set { SetValue(LeftAlignedTextProperty, value); }
    }
    public static readonly DependencyProperty LeftAlignedTextProperty =
        DependencyProperty.Register("LeftAlignedText", typeof(string), typeof(ExtendedTextBlock), new PropertyMetadata(SetText));

    public static void SetText(object sender, DependencyPropertyChangedEventArgs args)
    {
        SetText((ExtendedTextBlock)sender);
    }

    public static void SetText(ExtendedTextBlock owner)
    {
        if (owner.ActualWidth == 0)
            return;

        // helper function to get the width of a text string
        Func<string, double> getTextWidth = text =>
        {
            var formattedText = new FormattedText(text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight,
                new Typeface(owner.FontFamily, owner.FontStyle, owner.FontWeight, owner.FontStretch),
                owner.FontSize,
                Brushes.Black);
            return formattedText.Width;
        };

        // calculate the space needed to fill in
        double spaceNeeded = owner.ActualWidth - getTextWidth(owner.LeftAlignedText ?? "") - getTextWidth(owner.RightAlignedText ?? "");

        // get the width of an empty space (have to cheat a bit since the width of an empty space returns zero)
        double spaceWidth = getTextWidth(" .") - getTextWidth(".");
        int spaces = (int)Math.Round(spaceNeeded / spaceWidth);

        owner.Text = owner.LeftAlignedText + new string(Enumerable.Repeat(' ', spaces).ToArray()) + owner.RightAlignedText;
    }

    public ExtendedTextBlock()
    {
        SizeChanged += (sender, args) => SetText(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

2)使用InlineUIContainer添加对齐文本

这里的想法是在里面添加一个面板,TextBlock它将负责对齐每个文本字符串.这是基本的想法:

<TextBlock>
    <InlineUIContainer>
        <Grid Width="{Binding RelativeSource={RelativeSource AncestorType=TextBlock},Path=ActualWidth}">
            <TextBlock Text="Hello" />
            <TextBlock Text="World" TextAlignment="Right" />
        </Grid>
    </InlineUIContainer>
</TextBlock>
Run Code Online (Sandbox Code Playgroud)

因此,此版本的控件重新创建上述内容但隐藏了实现.它将InlineUIContainer控件添加到基础TextBlock,并保持对"左"和"右" TextBlock的引用,根据需要设置其文本.

public class ExtendedTextBlock2 : TextBlock
{
    private TextBlock _left, _right;

    public string RightAlignedText
    {
        get { return (string)GetValue(RightAlignedTextProperty); }
        set { SetValue(RightAlignedTextProperty, value); }
    }
    public static readonly DependencyProperty RightAlignedTextProperty =
        DependencyProperty.Register("RightAlignedText", typeof(string), typeof(ExtendedTextBlock2), new PropertyMetadata(SetText));

    public string LeftAlignedText
    {
        get { return (string)GetValue(LeftAlignedTextProperty); }
        set { SetValue(LeftAlignedTextProperty, value); }
    }
    public static readonly DependencyProperty LeftAlignedTextProperty =
        DependencyProperty.Register("LeftAlignedText", typeof(string), typeof(ExtendedTextBlock2), new PropertyMetadata(SetText));

            public static void SetText(object sender, DependencyPropertyChangedEventArgs args)
    {
        ((ExtendedTextBlock2)sender).SetText();
    }

    public void SetText()
    {
        if (_left == null || _right == null)
            return;
        _left.Text = LeftAlignedText;
        _right.Text = RightAlignedText;
    }

    public ExtendedTextBlock2()
    {
        Loaded += ExtendedTextBlock2_Loaded;
    }

    void ExtendedTextBlock2_Loaded(object sender, RoutedEventArgs e)
    {
        Inlines.Clear();
        var child = new InlineUIContainer();
        var container = new Grid();
        var widthBinding = new Binding { Source = this, Path = new PropertyPath(TextBlock.ActualWidthProperty) };
        container.SetBinding(Grid.WidthProperty, widthBinding);
        child.Child = container;
        container.Children.Add(_left = new TextBlock { HorizontalAlignment = System.Windows.HorizontalAlignment.Left });
        container.Children.Add(_right = new TextBlock { HorizontalAlignment = System.Windows.HorizontalAlignment.Right });
        Inlines.Add(child);

        SetText();
    }
}
Run Code Online (Sandbox Code Playgroud)