【问题标题】:How to center header texts on TabItems如何在 TabItems 上居中标题文本
【发布时间】:2024-01-13 15:10:01
【问题描述】:

我正在尝试让我的 WPF TabItems 使其标题文本居中。但无论我在 ContentPresenter 及其包含的 Border 上设置了 Horizo​​ntalAlignment 和 Horizo​​ntalAlignment(居中或拉伸)的哪种组合,文本总是显示为左对齐,而不是居中。我也没有在 TabItems 上看到可以用来直接在选项卡项本身上设置它的属性(事实证明,TabItem 上的 Horizo​​ntalAlignment 做了完全不同的事情)。

我现在的代码是这样的:

<Grid TextElement.Foreground="White" TextElement.FontSize="17" TextElement.FontFamily="Times New Roman" HorizontalAlignment="Center" >
   <Border Name="TabBorder" BorderThickness="8 8 8 0"  CornerRadius="12 12 0 0"  
           Background="{StaticResource bandBrush}" HorizontalAlignment="Center" >
   <ContentPresenter HorizontalAlignment="Stretch" ContentSource="Header" Height="24" Width="100" />
   </Border>
 </Grid>

【问题讨论】:

    标签: c# wpf xaml header tabitem


    【解决方案1】:

    您可以将 ContentPresenter 放在 Label 中,将 Horizo​​ntalAlignment 属性设置为 Strecth,将 Horizo​​ntalContentAlignment 设置为 Center, 查看this:

    <Grid x:Name="gridTabItem">
      <Border x:Name="Border" Margin="0,0,0,0" BorderBrush="{x:Null}" CornerRadius="7,7,0,0" BorderThickness="0" >
        <Label  x:Name="label" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center">
          <ContentPresenter x:Name="ContentSite"
                          VerticalAlignment="Stretch"  
                     HorizontalAlignment="Center"
                     ContentSource="Header" Margin="10,2,10,2"
                     RecognizesAccessKey="True">
          </ContentPresenter>
        </Label>
    
      </Border>
      <Rectangle x:Name="rectangle" HorizontalAlignment="Left" Height="4" Margin="0,41, 0,0" Stroke="{x:Null}" VerticalAlignment="Top" Width="{Binding ActualWidth, ElementName=gridTabItem}" StrokeThickness="0" Fill="{x:Null}"/>
      <Rectangle x:Name="rectangle1" HorizontalAlignment="Left" Height="1" Margin="0,43,0,0" Stroke="{x:Null}" StrokeThickness="0" VerticalAlignment="Top" Width="{Binding ActualWidth, ElementName=gridTabItem}" Fill="#FFEEEEEE"/>
      <Rectangle x:Name="glow" HorizontalAlignment="Left" Height="41" Margin="0" Stroke="{x:Null}" StrokeThickness="0" VerticalAlignment="Top" Width="{Binding ActualWidth, ElementName=gridTabItem}" Fill="{x:Null}"/>
    </Grid>
    

    【讨论】:

    • 谢谢。如果我添加标签,将其 Horizo​​ntalAlignment 设置为 Stretch,将其 Horizo​​ntalContentAlignment 设置为 Center,然后将 contentPresenter 的 Horizo​​ntalAlignment 设置为 center,那么文本 still 会向左对齐。但是,如果我将您的代码而不是我自己的代码复制/粘贴到我的代码中,那么标题 居中!所以这段代码可能是正确的,尽管我仍然需要弄清楚为什么我自己的代码在我采用相同的结构和设置时不起作用。以后可能会接受这个答案...
    • 实际上,这可能与我在 ContentPresenter 上设置宽度有关吗? (上面的代码中没有显示,因为我已经删除了我认为不相关的内容。)当我删除宽度时,文本可能会居中 - 但很难看到,因为选项卡项变得太窄以至于文本正好适合里面(即 tabitem 宽度取决于文本占用的空间)。无论如何,这不是我想要的,我希望所有标签的宽度都相同,而与文本长度无关。
    • 实际上,当我简单地在 TabItem 上而不是在 ContentPresenter 上设置宽度时,它可以完美地工作。完美。
    【解决方案2】:

    我知道这个问题有点老了,并且已经接受了答案,但我认为我的答案可以帮助某人。

    我的问题是我需要均匀分布 TabItem 标题(每个 TabItem 标题具有相同的宽度)并且标题内的文本需要居中。所以这就是我实现这一目标的方式:

    TabControl.xaml

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:FMEA.Resources.Styles"
                    xmlns:Converters="clr-namespace:FMEA.Converters"
                    xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro">
    
    <Style x:Key="Custom_TabItem" BasedOn="{StaticResource {x:Type TabItem}}" TargetType="{x:Type TabItem}">
        <Setter Property="Width">
            <Setter.Value>
                <MultiBinding>
                    <MultiBinding.Converter>
                        <Converters:TabSizeConverter />
                    </MultiBinding.Converter>
                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}" />
                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}" Path="ActualWidth" />
                </MultiBinding>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid x:Name="tabItem">
                        <Border x:Name="Border">
                            <ContentPresenter x:Name="content"
                                              VerticalAlignment="Center"  
                                              HorizontalAlignment="Center"
                                              ContentSource="Header" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Foreground" Value="Gray" />
                        </Trigger>
                        <Trigger Property="IsSelected" Value="False">
                            <Setter Property="Foreground" Value="LightGray" />
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Foreground" Value="Black" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="HeaderTemplate">
            <Setter.Value>
                <DataTemplate DataType="{x:Type TabItem}">
                    <Border x:Name="border">
                        <ContentPresenter>
                            <ContentPresenter.Content>
                                <TextBlock Text="{TemplateBinding Content}"
                                           FontSize="22" HorizontalAlignment="Center" />
                            </ContentPresenter.Content>
                        </ContentPresenter>
                    </Border>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    </ResourceDictionary>
    

    TabSizeConverter 在哪里:

    class TabSizeConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            TabControl tabCtrl = values[0] as TabControl;
            double width = tabCtrl.ActualWidth / tabCtrl.Items.Count;
            return width <= 1 ? 0 : width - 1;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    使用示例:

    <TabItem Header="MyHeader" Style="{StaticResource Custom_TabItem}">
    

    【讨论】: