【问题标题】:How to align TextBlock and TextBox text on one baseline如何在一个基线上对齐 TextBlock 和 TextBox 文本
【发布时间】:2017-04-17 23:26:47
【问题描述】:

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

我有几个组合。

我希望相对面板能够提供对齐基线的选项,就像它与 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>

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

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

您对如何对齐基线有任何想法吗?这对于很多输入控件和标签来说是/或者可能是一个不错的布局想法?

【问题讨论】:

  • VerticalAlignment="Center" for Textbox in Horizo​​ntal StackPanel 应该可以解决问题

标签: layout uwp uwp-xaml


【解决方案1】:

我快速浏览了文档,我认为在 UWP 中没有任何与 Android 的基线对齐方式等效的内容。文本控件不会公开它们的基线位置以供面板使用,因为它高度依赖于控件的模板(可以完全更改,不像在 Android 中视图的视觉外观有点硬-编码)。

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

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

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


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

如果您要拥有很多这些左标记元素,一些建议:

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

似乎推荐的方法是使用 Header 属性并将标签放在顶部。大多数 UWP 应用程序都会这样做(在 Groove 中,当您编辑歌曲信息、Edge 的设置窗格等时)。这可能是因为在移动设备上显示时,水平空间不大。

【讨论】:

  • 感谢您的精彩回答,即使是图形。我明白你在说什么,但我希望有另一种方式。使用边距或填充有点烦人,因为必须确定哪些边距适合您使用的每个控件组合。也许字体在所有情况下都不相等。也许值得创建一个辅助函数来检查控件的可视化树/模板,搜索文本块元素并尝试计算基线。然后使用该功能甚至可以创建自己的布局面板。我稍后会接受:)
【解决方案2】:

实现您想要的最简单的方法是不要创建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 应该足以禁用所有潜在的交互(只是做了一个快速测试),但要确保你也可以简单地设置 @ 987654330@ 为 false 并修改模板使其看起来与启用时相同(您可以通过打开 Document Outline 窗口获取 VS2015 中的默认模板(如果您没有看到它,您可以在 View > Other windows 中找到它)打开可视化树以找到您的项目,然后右键单击,Edit Template 和 编辑副本...)。

【讨论】:

  • 感谢您的回答。而不是这个解决方案,我更喜欢带有边距的“解决方案”,因为它更适合其他控件,例如 Combobox、Checkbox 等。
  • 值得一提的是,这种方法对可访问性有非常负面的影响。例如,使用屏幕阅读器,虽然使用 TextBlocks 会按预期读取文本 (string 1, string 2),但 TextBox 会使屏幕读取更接近 string 1, edit, read only, disabled, string 2, edit, read only, disabled, 的内容。您可以使用自定义的 AutomationPeer 来缓解这种情况,但要正确处理会变得更加困难。我会坚持使用边距方法,因为默认情况下它确实具有可访问性。不过,这是解决令人沮丧的问题的一种有趣方法!
  • 糟糕!我误读了原来的问题。如果您更新我的示例以期望 string 1, edit 作为第一个元素的读数,我的原始评论仍然有效。
猜你喜欢
  • 2011-09-07
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
  • 2014-01-02
  • 2019-10-03
  • 1970-01-01
相关资源
最近更新 更多