xaml - xaml WPF灵活的TabControl标头

  显示原文与译文双语对照的内容
130 1

我想有一个带有多个 TabItemsTabControl这些 TabItems 都有标题文本。这些文本在长度( 。像 5字符长和 15个字符长) 中可以能不同。

我希望 TabControl 只在一行中对齐标题。

所有选项卡头应使用相同的宽度,当有足够的空间时,我希望使用所有可以用的空间。

所以如果我想使用vMaxWidth`的100个项目,选项卡标题应该是最宽的7.如果有更多可用空间,则应将它的忽略。

如果可以用空间较少,我希望空间在项目之间均等分布。如果文本被截断,我想使用 TextWrapping

我已经尝试了多种解决这里问题的方法,这是我当前的设置:

<Style x:Key="Style-TabControl-Main" TargetType="{x:Type TabControl}">
 <Setter Property="SnapsToDevicePixels" Value="True"/>
 <Setter Property="Template">
 <Setter.Value>
 <ControlTemplate TargetType="{x:Type TabControl}">
 <Grid KeyboardNavigation.TabNavigation="Local">
 <Grid.RowDefinitions>
 <RowDefinition Height="Auto"/>
 <RowDefinition Height="*"/>
 </Grid.RowDefinitions>
 <Grid.ColumnDefinitions>
 <ColumnDefinition Width="*"/>
 <ColumnDefinition Width="Auto"/>
 </Grid.ColumnDefinitions>
 <Border BorderThickness="0,0,0,1" Margin="13,0,0,0" BorderBrush="{StaticResource Brush-White}">
 <StackPanel Panel.ZIndex="1" x:Name="HeaderPanel" IsItemsHost="True" KeyboardNavigation.TabIndex="1" Background="Transparent" 
 Orientation="Horizontal"/>
 </Border>
 <Border x:Name="Border"
 Grid.Row="1" Grid.ColumnSpan="2"
 KeyboardNavigation.TabNavigation="Local"
 KeyboardNavigation.DirectionalNavigation="Contained"
 KeyboardNavigation.TabIndex="2"
 BorderThickness="{TemplateBinding BorderThickness}"
 Background="{TemplateBinding Background}"
 BorderBrush="{TemplateBinding BorderBrush}">
 <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>
 </Border>
 </Grid>
 </ControlTemplate>
 </Setter.Value>
 </Setter>
</Style>

还有 TabItemStyle

<Style x:Key="Style-TabItem-Main" TargetType="{x:Type TabItem}">
 <Setter Property="Height" Value="31"/>
 <Setter Property="Width" Value="180"/>
 <Setter Property="Foreground" Value="{DynamicResource Brush-BrightRegular-Foreground}"/>
 <Setter Property="Template">
 <Setter.Value>
 <ControlTemplate TargetType="{x:Type TabItem}">
 <Border x:Name="Border" Cursor="Hand" 
 Margin="2,0,0,0"
 BorderThickness="1,1,1,0"
 CornerRadius="4,4,0,0"
 BorderBrush="{DynamicResource Brush-BrightRegular-Background}"
 Background="{DynamicResource Brush-White}">
 <ContentPresenter x:Name="Content" VerticalAlignment="Center" HorizontalAlignment="Stretch" ContentSource="Header" RecognizesAccessKey="True"
 TextBlock.TextAlignment="Center" TextBlock.FontSize="16"/>
 </Border>
 <ControlTemplate.Triggers>
 <Trigger Property="IsSelected" Value="True">
 <Setter Property="Foreground" Value="{DynamicResource Brush-White}"/>
 <Setter TargetName="Border" Property="Background" Value="{DynamicResource Brush-DefaultDark-Background}"/>
 </Trigger>
 </ControlTemplate.Triggers>
 </ControlTemplate>
 </Setter.Value>
 </Setter>
</Style>

当你调整默认 TabControl的大小时,我使用 StackPanel 而不是 TabPanel 来消除"堆叠"。但是,我无法将我的其他需求工作。我试图将 MaxWidth ( 而不是固定宽度) 应用于 TabItem 标头,但当然这不起作用,因为该项不会缩小到最小所需的大小。

时间:原作者:0个回答

131 2

步骤 1 ( 第一次尝试):将标题放在一行中,并给每个头赋予相同的宽度。

这可以以通过使用 UniformGrid 而不是标准,来实现,并将它的行计数锁定到 1.以下是你的TabControl 样式的一个精简版本:

<Style x:Key="Style-TabControl-Main" TargetType="{x:Type TabControl}">
 <Setter Property="SnapsToDevicePixels" Value="True"/>
 <Setter Property="Template">
 <Setter.Value>
 <ControlTemplate TargetType="{x:Type TabControl}">
 <Grid>
 <Grid.RowDefinitions>
 <RowDefinition Height="Auto"/>
 <RowDefinition Height="*"/>
 </Grid.RowDefinitions>
 <Border>
 <UniformGrid x:Name="HeaderPanel" IsItemsHost="True" 
 Rows="1"/>
 </Border>
 <Border x:Name="Border" Grid.Row="1" 
 BorderThickness="{TemplateBinding BorderThickness}"
 Background="{TemplateBinding Background}"
 BorderBrush="{TemplateBinding BorderBrush}">
 <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>
 </Border>
 </Grid>
 </ControlTemplate>
 </Setter.Value>
 </Setter>
</Style>

步骤 2: 将标题限制为 MaxWidth 并应用文本换行。

可以在 TabItem 样式中设置 MaxWidth,以及一个包装文本( 你仍然可以在这里使用自定义 ControlTemplate 来样式化TabItem部件)的HeaderTemplate:

<Style x:Key="Style-TabItem-Main" TargetType="{x:Type TabItem}">
 <Setter Property="MaxWidth" Value="100"/>
 <!--https://social.msdn.microsoft.com/forums/vstudio/en-US/df4f7fc3-f0ec-4ed1-a022-a32650e49cb3/how-to-wrap-header-text-in-tabcontrol-->
 <Setter Property="HeaderTemplate"> 
 <Setter.Value>
 <DataTemplate>
 <TextBlock Text="{Binding}" TextWrapping="Wrap"/>
 </DataTemplate>
 </Setter.Value>
 </Setter>
 <Setter Property="Template">
. . .
 </Setter>
</Style>


如果你在步骤 2 应用 MaxWidth,那么你可能希望在TabControl太宽时左对齐。

<UniformGrid x:Name="HeaderPanel" IsItemsHost="True" 
 Rows="1" HorizontalAlignment="Left"/>

但是,不希望当还未到达rtc时,项目应该跨越整个部分of的整个宽度。因此我们需要一种方法,根据项目的是否已经达到这个值来确定该 HorizontalAlignment

步骤 1 ( 重新):让我们尝试制作自己的UniformGrid:

public class UniformTabPanel : UniformGrid
{
 public UniformTabPanel()
 {
 this.IsItemsHost = true;
 this.Rows = 1;
//Default, so not really needed..
 this.HorizontalAlignment = HorizontalAlignment.Stretch;
 }
 protected override Size MeasureOverride(Size constraint)
 {
 var totalMaxWidth = this.Children.OfType<TabItem>().Sum(tab => tab.MaxWidth);
 if (!double.IsInfinity(totalMaxWidth))
 {
 this.HorizontalAlignment = (constraint.Width> totalMaxWidth) 
? HorizontalAlignment.Left 
 : HorizontalAlignment.Stretch;
 }
 return base.MeasureOverride(constraint);
 }
}

现在,我们可以用这个新面板替换 TabControl 样式中的UniformGrid:

. . .
 <Border>
 <mycontrols:UniformTabPanel x:Name="HeaderPanel"/>
 </Border>
. . .

。TabControl应该作为expeced函数。

原作者:
...