我使用this作为为TabControl制作样式的起点,我的仅适用于TabStripPlacement =“Bottom”。我希望我放入 TabItem 中的内容将填充为其指定的整个区域,就像使用默认样式和我用作起点的 Microsoft 样式一样。但事实并非如此,它从最小尺寸开始,按钮根本不会拉伸,而且 RichTextBox 似乎仅水平拉伸,如果我向 RichTextBox 添加文本,它就会扩展。 这是它的样子:
橙色是我期望内容占据的区域(有一些边距),蓝色是 RichTextBox 的背景。绿色是全局背景。所选选项卡的标题边框加粗(红色)。不要介意选项卡标题和内容区域之间的空格,这是故意的。
我已经查了很多,但似乎找不到原因,但是我发现如果我不应用 TabItem 的样式,就不会出现此问题。当我在 Visual Studio 中使用 xaml 调试工具检查元素时,我发现 PART_SelectedContentHost 的水平对齐设置为“左”,垂直对齐设置为“顶部”,即使我已在样式中将它们显式设置为“拉伸”,也会发生这种情况。我还尝试对 RichTextBox 应用“Stretch”,但没有成功。这是风格:
<Style TargetType="{x:Type TabControl}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid KeyboardNavigation.TabNavigation="Local" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#FFAAAAAA" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TabPanel x:Name="HeaderPanel"
Grid.Row="2"
Panel.ZIndex="1"
Margin="0"
IsItemsHost="True"
KeyboardNavigation.TabIndex="1"
Background="Transparent" />
<Border x:Name="Border"
Grid.Row="0"
Panel.ZIndex="0"
BorderThickness="0"
CornerRadius="0"
KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
<Border.Background>
<SolidColorBrush Color="Orange"/>
</Border.Background>
<ContentPresenter
x:Name="PART_SelectedContentHost"
Margin="4,4,4,4"
ContentSource="SelectedContent"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TabItem}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid x:Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimation Storyboard.TargetName="ContentSite"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
From="White" To="Blue"
Duration="0:0:0.0" AutoReverse="True"/>
<ThicknessAnimationUsingKeyFrames
Storyboard.TargetProperty="(Border.BorderThickness)"
Storyboard.TargetName="Border">
<EasingThicknessKeyFrame KeyTime="0"
Value="1,5,1,5" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border"
Margin="0,0,0,0"
BorderThickness="1,1,1,1"
CornerRadius="0,0,0,0"
BorderBrush="Red">
<Border.Background>
<SolidColorBrush Color="Black"/>
</Border.Background>
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"
RecognizesAccessKey="True"
TextBlock.Foreground="White"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
编辑:为了清楚起见,样式保存在 xaml 文件中 - “TabControlStyleDictionary.xaml”,这是主窗口的代码:
<Window x:Class="TabControlStylingTest2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TabControlStylingTest2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="TabControlStyleDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid Background="Green">
<TabControl TabStripPlacement="Bottom">
<TabItem Header="tab1">
<RichTextBox
Foreground="White"
Background="Blue"
AcceptsReturn="True"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"/>
</TabItem>
<TabItem Header="tab2">
<Button
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
some text 123456789
</Button>
</TabItem>
</TabControl>
</Grid>
我在覆盖样式时遇到了同样的问题。由于某种原因,ContentPresenter 的 HorizontalAlignment 和 VerticalAlignment 属性在代码隐藏中的 PART_SelectedContentHost 的每个 LayoutUpdate 上本地设置。在我的解决方案中,我为 UIElements 实现了一个附加行为,它在 LayoutUpdate 事件上调用 ClearValue 方法。这将删除每次事件发生时的本地值。为此需要引用 System.Windows.Interactivity。
public class ClearValueOnLayoutUpdateBehavior : Behavior<UIElement>
{
public static readonly DependencyProperty PropertyProperty =
DependencyProperty.Register(nameof(Property), typeof(DependencyProperty), typeof(ClearValueOnLayoutUpdateBehavior), new PropertyMetadata());
public DependencyProperty Property
{
get { return (DependencyProperty)GetValue(PropertyProperty); }
set { SetValue(PropertyProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
if(Property != null)
AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
}
private void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
{
AssociatedObject.ClearValue(Property);
}
}
在您的 XAML 文件中,您还必须添加
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
引用。您的 ContentPresenter 应更改如下:
<ContentPresenter
x:Name="PART_SelectedContentHost"
ContentSource="SelectedContent"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<i:Interaction.Behaviors>
<behavior:ClearValueOnLayoutUpdateBehavior Property="{x:Static FrameworkElement.HorizontalAlignmentProperty}" />
<behavior:ClearValueOnLayoutUpdateBehavior Property="{x:Static FrameworkElement.VerticalAlignmentProperty}" />
</i:Interaction.Behaviors>
</ContentPresenter>
您需要在 TabItem 上设置 HorizontalContentAlignment 和 VerticalContentAlignment 属性。
TabControl 的代码隐藏 获取这些属性的值并将它们分配给 PART_SelectedContentHost ContentPresenter 的 HorizontalAlignment 和 VerticalAlignment 属性。