解决方法
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();
- }
- }