解决方法
TextBlock本质上反对对齐孩子的概念,但当然有一些可能的黑客攻击:
>填写空格以给出对齐的外观.
>使用InlineUIContainer
在TextBlock中添加实际的UI元素(可以对齐).
我将通过创建具有LeftAlignedText和RightAlignedText属性的ExtendedTextBlock控件给出每个示例.用法是这样的:
<my:ExtendedTextBlock RightAlignedText=":" LeftAlignedText="My associated textBox is" />
1)用空格填充.
对于这种方法,我从this answer借来获得文本字符串的实际宽度.这个想法基本上是从控件的实际宽度中减去文本的总宽度,并在它们之间插入适当数量的空格.
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",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); } }
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>
因此,此版本的控件重新创建上述内容但隐藏了实现.它将InlineUIContainer控件添加到基本TextBlock,并保持对“左”和“右”TextBlocks的引用,根据需要设置其文本.
public class ExtendedTextBlock2 : TextBlock { private TextBlock _left,_right; public string RightAlignedText { get { return (string)GetValue(RightAlignedTextProperty); } set { SetValue(RightAlignedTextProperty,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(); } }