WPF超越TabControl的Tab内容对齐方式

时间:2018-11-29 18:08:26

标签: wpf tabcontrol styling

我以this为起点为TabControl制作样式,我的仅与TabStripPlacement =“ Bottom”一起使用。我希望我放入TabItem的内容将填充为其指定的整个区域,就像它使用默认样式以及我用作起点的Microsoft样式一样。但事实并非如此,它以最小的尺寸开始,按钮根本不会拉伸,并且RichTextBoxes似乎只是水平拉伸,如果我在RichTextBox中添加文本则它会扩展。外观如下:

No text Some text

橙色是我希望内容占据的区域(有一些边距),蓝色是RichTextBox的背景。绿色是全球背景。所选选项卡的标题边框变粗(红色)。不要介意标签页眉和内容区域之间的空间,这是故意的。

我一直在闲逛很多,但似乎找不到原因,但是我发现如果不对TabItem应用样式,我就不会遇到这个问题。当我在Visual Studio中使用xaml调试工具检查元素时,我发现PART_SelectedContentHost的水平对齐方式设置为Left,垂直对齐方式设置为Top,即使我已将样式中的元素明确设置为Stretch。我也尝试将“ Stretch”应用于RichTextBox,但没有成功。这是样式:

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

1 个答案:

答案 0 :(得分:0)

在我的样式覆盖上存在相同的问题,由于某种原因,Horizo​​ntalAlignment和VerticalAlignment属性在后面的代码中的PART_SelectedContentHost的每个LayoutUpdate上设置为本地。在我的解决方案中,我实现了UIElements的附加行为,该行为在LayoutUpdate事件上调用ClearValue方法。这将删除每个事件的本地值。为此,需要对System.Windows.Interactivity进行刷新。

public class ClearValueOnLayoutUpdateBehavior<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>