如何在一个基线上对齐TextBlock和TextBox文本

时间:2016-12-02 23:47:05

标签: layout uwp uwp-xaml

我正在尝试为一组带标签的控件找出一个不错的布局。例如,如果我在文本框的左侧有一个标签,则标签的基线和文本框不在同一垂直位置。一个经常解决方法是将两个控件垂直居中,但如果你有多行文本框控件那么看起来并不好看。

我有几个组合。

我希望相对面板提供与基线对齐的选项,就像它与android相对布局面板一样。不幸的是,它没有。

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  <RelativePanel>
    <TextBlock Text="Name:" Name="t1"></TextBlock>
    <TextBox Text="Content" RelativePanel.RightOf="t1" ></TextBox>
  </RelativePanel>
</Grid>

网格也无济于事。

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Column="0" Text="{x:Bind Label}" Style="{ThemeResource BaseTextBlockStyle}"/>
    <TextBox Grid.Column="1" Text="Content" HorizontalAlignment="Stretch"></TextBox>
  </Grid>
</Grid>

显然,水平堆叠面板也没有魔力。

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  <StackPanel Orientation="Horizontal">
    <TextBlock Grid.Column="0" Text="{x:Bind Label}" Style="{ThemeResource BaseTextBlockStyle}"/>
    <TextBox Grid.Column="1" Text="Content" VerticalAlignment="Top"></TextBox>
  </StackPanel>
</Grid>

垂直stackpanel可以避免这个问题,但我更喜欢控件左侧的标签。

  <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel Orientation="Vertical">
      <TextBlock Grid.Column="0" Text="{x:Bind Label}" Style="{ThemeResource BaseTextBlockStyle}"/>
      <TextBox Grid.Column="1" Text="Content" ></TextBox>
    </StackPanel>
  </Grid>

您是否有任何想法如何为许多输入控件和标签对齐基线,这可能是一个不错的布局想法?

2 个答案:

答案 0 :(得分:3)

我快速查看了文档,我认为在UWP中没有任何与Android基线对齐相同的内容。文本控件不会公开其基线的位置以供面板使用,因为它高度依赖于控件的模板(可以完全改变,不像在Android中,视图的视觉外观类似于硬编码)。

无论如何,通过检查文本框的可视化树,我发现最里面的TextBoxView(实际显示和处理TextBox控件的文本输入的控件)以与TextBlock相同的方式呈现文本(意味着填充和这是一样的)。因此,只要我们可以将TextBlock的顶部边缘与TextBoxView对齐,那么两个控件的文本将处于相同的垂直位置。当然,两个控件的字体和字体大小必须相同(默认情况下)。

TextBoxView被其父ScrollContentPresenter向下推3px(有效像素),文本框边框按2px向下推。因此,您只需要向TextBlock添加5px的上边距,两个控件的文本将对齐。

Screenshot

仅供参考,这是基于我正在使用的SDK版本14393提供的默认TextBox模板。 Microsoft可以使用新的SDK版本更改这些样式。

查看Android文档,View类有一个方法getBaseline;在UWP中,UIElement(或FrameworkElement)没有这样的等价物。搜索可视树并尝试确定您看到的第一个文本元素的基线在每种情况下都不起作用(某些元素具有多个文本元素)。

如果你有很多这些左标记元素,可以提出一些建议:

  • 创建一个UserControl,标签和文本框位于正确的位置。这样,您只需在代码中的一个位置硬编码边距,如果您需要更改它,您只需要更改一段代码。
  • TextBox控件(与许多其他控件一样)具有Header属性,您可以在其中指定将在文本框正上方显示的文本。您可以更改模板,以便标题位于文本框的左侧。

似乎推荐的方法是使用Header属性并将标签放在顶部。大多数UWP应用都会执行此操作(在编辑歌曲信息时使用Groove,Edge的设置窗格等)。这可能是因为当在移动设备上显示时,没有多少水平空间。

答案 1 :(得分:0)

实现目标的最简单方法是不创建TextBlockTextBox,而只创建两个TextBox元素,其中包含您在顶部建议的任何布局。然后将以下样式应用于TextBox元素,该元素应仅显示标签,使其看起来像TextBlock

<Style x:Key="TransparentTextBoxStyle" TargetType="TextBox">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="IsReadOnly" Value="True" />
    <Setter Property="IsTapEnabled" Value="False" />
    <Setter Property="IsTabStop" Value="False" />
</Style>

认为设置IsReadOnlyIsTapEnabledIsTabStop应该足以禁用所有潜在的互动(只是做了快速测试),但要确定您也可以简单地将IsEnabled设置为false,并将模板修改为相同,如果它将被启用(您可以通过打开文档大纲窗口获取VS2015中的默认模板(如果你没有看到它,你可以在查看&gt; 其他窗口中找到它)打开可视树来找到你的项目,然后右键单击, 编辑模板编辑副本... )。