WPF 重写 TabControl 的选项卡内容对齐方式

问题描述 投票:0回答:2

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

No text Some text

橙色是我期望内容占据的区域(有一些边距),蓝色是 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>

wpf tabcontrol styling
2个回答
1
投票

我在覆盖样式时遇到了同样的问题。由于某种原因,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>

0
投票

您需要在 TabItem 上设置 HorizontalContentAlignmentVerticalContentAlignment 属性。

TabControl 的代码隐藏 获取这些属性的值并将它们分配给 PART_SelectedContentHost ContentPresenter 的 HorizontalAlignment 和 VerticalAlignment 属性。

© www.soinside.com 2019 - 2024. All rights reserved.