15

我有一个我重新设计的 TabControl。The TabItem has a trigger that is fired when the TabItem is selected that changes the TabItem text to bold and green. 我遇到的问题是选项卡内容中的文本也设置为粗体和绿色。

我可以通过将选项卡内容中的所有控件设置为我想要的颜色和字体粗细来解决这个问题,但我应该这样做吗?因此,我必须确保内容区域中的每个文本块都具有将颜色设置为黑色且字体粗细正常的样式。

如何将 TabItem 的 IsSelected 部分设置为显示绿色,但不保留选项卡的内容?

我试图将 TabControl 的前景设置为黑色,但这不起作用。

您将从下面的代码示例中看到,第一个选项卡上的文本是绿色的,我希望它是黑色的,但没有在选项卡内容中设置每个控件。

下面的代码示例:

    <Grid>
    <Grid.Resources>
        <!-- Tab item -->
        <Style TargetType="{x:Type TabItem}">
            <Setter Property="FontSize" Value="14"/>
            <Setter Property="MinWidth" Value="200"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabItem}">
                        <Grid>
                            <Border Name="Border" Padding="5,2">
                                <ContentPresenter ContentSource="Header"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Border.IsMouseOver" Value="True"/>
                                    <Condition Property="IsSelected" Value="False"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="FontWeight" Value="Bold"/>
                                <Setter Property="Foreground" Value="Black"/>
                            </MultiTrigger>

                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="Border.IsMouseOver" Value="False"/>
                                    <Condition Property="IsSelected" Value="False"/>
                                </MultiTrigger.Conditions>
                                <Setter Property="Foreground" Value="Black" />
                            </MultiTrigger>

                            <Trigger Property="IsSelected" Value="True">
                                <Setter Property="Foreground" Value="Green"/>
                                <Setter Property="FontWeight" Value="Bold"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!-- Tab control -->
        <Style  TargetType="{x:Type TabControl}">
            <Setter Property="SelectedIndex" Value="0"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabControl}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="200" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Border Grid.Column="0" Padding="5" Margin="0,0,5,0" CornerRadius="3">
                                <StackPanel Orientation="Vertical">
                                    <ScrollViewer VerticalScrollBarVisibility="Auto" FocusVisualStyle="{x:Null}">
                                        <TabPanel IsItemsHost="True"/>
                                    </ScrollViewer>
                                </StackPanel>
                            </Border>
                            <Border Grid.Column="1" BorderBrush="Black" BorderThickness="0">
                                <ScrollViewer VerticalScrollBarVisibility="Auto" FocusVisualStyle="{x:Null}" Padding="10,0">
                                    <ContentPresenter ContentSource="SelectedContent"/>
                                </ScrollViewer>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Grid.Resources>

    <TabControl Name="tabControl" TabStripPlacement="Left">
        <!-- First tab item -->
        <TabItem IsSelected="True">
            <TabItem.Header>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Profile"/>
                </StackPanel>
            </TabItem.Header>
            <TextBlock Text="Page 1 Sample Text with no foreground set." FontSize="30"/>
        </TabItem>

        <!-- Second tab item -->
        <TabItem IsSelected="True">
            <TabItem.Header>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Profile"/>
                </StackPanel>
            </TabItem.Header>
            <TextBlock Text="Page 2 Sample Text with foreground set manually." FontSize="30" Foreground="Red"/>
        </TabItem>
    </TabControl>
</Grid>
4

5 回答 5

12

我刚刚遇到了同样的问题,在摆弄了一下之后,我想我找到了一个更优雅的解决方案。

我说的更优雅,因为它会使 ContentPresenter 保持原样,并将前景和字体重量设置器应用于 ContentPresenter 的 TextElement(这基本上是一个附加属性,但这不是重点)。

这种方法的主要优点是,将 ContentPresenter 替换为 TextBlock 会隐式假定标题仅包含文本,这会限制解决方法的可用性并产生不太健壮的代码。保留 ContentPresenter 将允许任何内容,例如图像+文本。

您还需要做的另一件事是为您的 ContentPresenter 命名:

<Setter Property="Template">
     <Setter.Value>
         <ControlTemplate TargetType="{x:Type TabItem}">
             <Grid>
                <Border Name="Border" Padding="5,2">
                   <ContentPresenter x:Name="CP" ContentSource="Header"/>
                </Border>
             </Grid>
             <ControlTemplate.Triggers>
                <MultiTrigger>
                   <MultiTrigger.Conditions>
                      <Condition Property="Border.IsMouseOver" Value="True"/>
                      <Condition Property="IsSelected" Value="False"/>
                   </MultiTrigger.Conditions>
                     <Setter Property="TextElement.FontWeight" TargetName="CP" Value="Bold"/>
                     <Setter Property="TextElement.Foreground" TargetName="CP" Value="Black"/>                                
                </MultiTrigger>...

现在 Foreground 和 FontWeight 将不会被 TabItem 的内容继承(已测试)。

享受 :)

于 2011-04-21T18:09:13.303 回答
4

这已经很老了,但是我在寻找类似问题的答案时遇到了它,我发现提供的答案根本没有帮助。这是我解决此问题的方法。

如果您在 tabitem 的控制模板中将 ContentPresenter 更改为 TextBlock,如下所示:

....stuff above here...
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
   <Border Name="Border" Padding="5,2">
        <TextBlock x:Name="TabItemContent" Text="{TemplateBinding Header}"/>
   </Border>
</Grid>
... stuff below here....

然后在该控件模板上的触发器中,您在 IsSelected 触发器中指定目标名称..即。

...stuff above here...
 <Trigger Property="IsSelected" Value="True">
     <Setter Property="Foreground" TargetName="TabItemContent" Value="Green"/>
     <Setter Property="FontWeight" Value="Bold"/>
</Trigger>
... stuff below here ...

这应该在选择选项卡时为您提供绿色文本,而不是所有其他时间为绿色,同时将文本着色留在应用程序的其余部分。

于 2010-12-08T21:13:50.783 回答
3

不幸的是,如果您通过某些触发器在 ContentPresenter 上设置了 Foreground(或 FontWeight),您仍然假设标题将仅包含 Text。

如果您设置 Header="SomeHeaderName"(即仅文本),ContentPresenter 将生成一个 TextBlock 来承载此 headertext;ContentPresenter 将是此 TextBlock 的(逻辑)父级,因此,在 ContentPresenter 上设置的新 Foreground 将由此 TextBlock 继承。这工作正常。

但是,如果为 Header 分配了一些可视树,例如带有 Image 和 TextBlock(甚至单个 TextBlock)的水平 StackPanel,则 StackPanel 的逻辑父级是 TabItem 而不是 ContentPresenter。继承通过逻辑树进行,因此 StackPanel 中的 TextBlock 最终将再次从 TabItem 继承其 Foreground;在 ContentPresenter 上设置的前景对此没有任何影响。

一种可能的解决方案:一个DataTemplate最终应用到一个ContentPresenter,所以DataTemplate的根的TemplatedParent就是ContentPresenter;并且继承也通过 TemplatedParent-Child 屏障起作用。所以如果你能够设置 TabItem.HeaderTemplate 而不是 TabItem.Header,那么你可以在 header 的 ContentPresenter 上设置 Foreground,因为 HeaderTemplate 的根会从 ContentPresenter 继承 Foreground。但是,SelectedContent 不会,因为未在 TabItem 上设置 Foreground(并且内容从 TabItem 继承其 Foreground)。

希望这可以帮助!

于 2011-08-30T17:50:02.427 回答
0

wpf 中的每个控件都从其父控件继承属性。由于 TabItem 的颜色是黑色,因此它的子textblock项也是黑色。现在,由于您已将整个 TabItem 的前景色更改为绿色,它的所有子项都将继承它。

在这里您可以将您的 TabItem.Header 或其内容的前景设置为绿色,这样就不会影响 TabItem 中的其他内容。否则,您可以反转解决方案。

否则试试这个:

<Window.Resources>
    <DataTemplate x:Key="greenHeaderTemplate">
        <StackPanel Orientation="Horizontal"> 
            <TextBlock Text="Profile" 
                       FontWeight="Bold" 
                       Foreground="Green"/> 
        </StackPanel> 
    </DataTemplate>
    <DataTemplate x:Key="defaultHeaderTemplate">
        <StackPanel Orientation="Horizontal"> 
            <TextBlock Text="Profile"/> 
        </StackPanel> 
    </DataTemplate>
</Window.Resources>

<Trigger Property="IsSelected" Value="True">      
    <Setter Property="HeaderTemplate" 
            Value="{StaticResource greenHeaderTemplate}"/> 
</Trigger>

<TabItem IsSelected="True" HeaderTemplate="{StaticResource defaultHeaderTemplate}"> 
    <TextBlock Text="Page 1 Sample Text with no foreground set." FontSize="30"/> 
</TabItem>
于 2010-06-21T10:12:07.423 回答
0

这是一个实用的解决方案,它假定黑色将是 TabItem 中 TextBlocks 等可接受的前景色。

首先,因为我使用 Canvas 作为我的 TabItem 的主体,所以我制作了这样的自定义样式:

<Style x:Key="canvasStyle_BlackForeground" TargetType="{x:Type Canvas}">
    <Setter Property="TextElement.Foreground" Value="Black"/>
</Style>

然后,TabItem(恰好使用 Canvas 作为容器)看起来像这样,其中 TabItem Foreground 设置为 Green,但 Canvas 的样式设置为 Foreground black:

<TabItem Header="TabItem" Foreground="Green">
            <Canvas Background="#FFE5E5E5" Style="{StaticResource canvasStyle_BlackForeground}">
                <TextBlock Canvas.Left="79" Text="This is a TextBlock" Canvas.Top="63"/>
            </Canvas>
        </TabItem>

如果您使用的是 Grid 而不是 Canvas,它也同样有效。只需将样式的 TargetType 设置为 x:Type Grid。

于 2022-01-13T01:50:09.100 回答