设置 TabItem 前景色也会设置 TabControl 前景色
我有一个已重新设计的 TabControl。 TabItem 有一个触发器,当选择 TabItem 时会触发该触发器,将 TabItem 文本更改为粗体和绿色。我遇到的问题是选项卡内容中的文本也设置为粗体和绿色。
我可以通过将选项卡内容中的所有控件设置为我想要的颜色和字体粗细来解决此问题,但我是否必须这样做?因此,我必须确保内容区域中的每个文本块都具有将颜色设置为黑色并将字体粗细设置为正常的样式。
如何将 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>
I have a TabControl that I have restyled. The TabItem has a trigger that is fired when the TabItem is selected that changes the TabItem text to bold and green. The problem I have is that the text in the contents of the tab is also set to bold and green.
I can work around this by setting all of my controls in the tab content to be the color and font weight I want, but should I have to do this? So, I have to make sure that every textblock in the contents area has a style that sets the color to black and font weight normal.
How can I set the IsSelected part of the TabItem to show green, but leave the contents of the tab alone?
I've tried to set the foreground of the TabControl to black, but this doesn't work.
You will see from the code sample below that the text on the first tab is green, and I want it to be black, but without setting each control in the tab content.
Code Sample below:
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我刚刚遇到了同样的问题,经过一番摆弄后,我想我找到了一个更优雅的解决方案。
我说的是更优雅,因为它会使 ContentPresenter 保持完整,并将前景和字体粗细设置器应用到 ContentPresenter 的 TextElement(这基本上是一个附加属性,但这不是重点)。
此方法的主要优点是,用 TextBlock 替换 ContentPresenter 隐式假定标头仅包含文本,这限制了解决方法的可用性并生成不太健壮的代码。将 ContentPresenter 留在原处将允许任何内容,例如图像+文本。
您还需要做的另一件事是命名您的 ContentPresenter:
现在 TabItem 的内容将不会继承 Foreground 和 FontWeight(已测试)。
享受 :)
I have just come across this very same problem, and after fiddling around with it a little I think I have found a more elegant solution.
I'm saying more elegant since it would leave the ContentPresenter intact, and apply the foreground and fontweight setters to the ContentPresenter's TextElement (which is basically an attached property, but that's beside the point).
The main advantage of this approach is that replacing the ContentPresenter with a TextBlock implicitly assumes that the header will only contain text, which limits the usability of the workaround and produces a less robust code. Leaving the ContentPresenter in place will allow any content, e.g. images+text.
One more thing you would have to do is name your ContentPresenter:
Now the Foreground and FontWeight will not be inherited by the contents of the TabItem (tested).
Enjoy :)
这是相当古老的,但我在寻找类似问题的答案时遇到了它,并且我发现提供的答案根本没有帮助。
这是我解决这个问题的方法。
如果您将 Tabitem 的控件模板中的 ContentPresenter 更改为 TextBlock,如下所示:
然后在该控件模板上的触发器中,您在 IsSelected 触发器中指定目标名称。
当选择选项卡时,这应该为您提供绿色文本,而在其他时间则不会为绿色,同时将文本着色保留在应用程序的其余部分中。
This is pretty old, but I came across it while looking for an answer for a similar problem, and I found the supplied answers not at all helpful.
Here is how I fixed this.
If you change the ContentPresenter to a TextBlock in the control template of your tabitem, like this:
Then in your trigger on that control template you specify the targetname in the IsSelected trigger..ie.
That should give you green text when the tab is selected, and not green all the other times, while leaving the text coloring in the rest of the app alone.
不幸的是,如果您通过某种触发器在 ContentPresenter 上设置 Foreground(或 FontWeight),您仍然认为标头仅包含文本。
如果您设置 Header=“SomeHeaderName”(即仅文本),ContentPresenter 将生成一个 TextBlock 来承载此标题文本; ContentPresenter 将是此 TextBlock 的(逻辑)父级,因此 ContentPresenter 上设置的新前景将由此 TextBlock 继承。这工作正常。
但是,如果为 Header 分配了视觉树的某个片段,例如具有图像和 TextBlock(甚至单个 TextBlock)的水平 StackPanel,则 StackPanel 的逻辑父级是 TabItem 而不是 ContentPresenter。继承通过逻辑树进行,因此 StackPanel 内的 TextBlock 最终将再次从 TabItem 继承其前景; ContentPresenter 上设置的前景对此没有任何影响。
一种可能的解决方案:DataTemplate最终应用到ContentPresenter,因此DataTemplate根的TemplatedParent就是ContentPresenter;继承也可以通过 TemplatedParent-Child 屏障起作用。因此,如果您能够设置 TabItem.HeaderTemplate 而不是 TabItem.Header,那么您可以在标头的 ContentPresenter 上设置 Foreground,因为 HeaderTemplate 的根将从 ContentPresenter 继承 Foreground。但是,SelectedContent 不会,因为未在 TabItem 上设置前景(并且内容从 TabItem 继承其前景)。
希望这有帮助!
Unfortunately, if you set the Foreground (or FontWeight) on a ContentPresenter by some trigger, you still assume that the header will only contain Text.
If you set Header="SomeHeaderName" (i.e. text only), the ContentPresenter will generate a TextBlock to host this headertext; the ContentPresenter will be the (logical) parent of this TextBlock and so, the new Foreground set on the ContentPresenter will be inherited by this TextBlock. This works ok.
However, if the Header is assigned some piece of visual tree, like a horizontal StackPanel with an Image and a TextBlock (or even a single TextBlock), then the logical parent of the StackPanel is the TabItem and not the ContentPresenter. Inheritance works via the logical tree and so the TextBlock inside the StackPanel will ultimately inherit its Foreground from the TabItem again; the foreground that was set on the ContentPresenter does not have any effect on this.
One possible solution: a DataTemplate is eventually applied to a ContentPresenter, so the TemplatedParent of the root of the DataTemplate is the ContentPresenter; and inheritance works through a TemplatedParent-Child barrier as well. So if you are able to set the TabItem.HeaderTemplate instead of the TabItem.Header, then you can set the Foreground on the header's ContentPresenter, because the root of the HeaderTemplate will inherit the Foreground from the ContentPresenter. The SelectedContent however, will not because the Foreground is not set on the TabItem (and the content inherits its Foreground from the TabItem).
Hope this helps!
wpf 中的每个控件都从其父控件继承属性。由于 TabItem 的颜色是黑色,因此它的子
textblock
也是黑色的。现在,由于您已将整个 TabItem 的前景色更改为绿色,因此它的所有子项都将继承它。在这里,您可以将 TabItem.Header 或其内容的前景设置为绿色,这样就不会影响 TabItem 中的其他内容。否则你可以反转解决方案。
否则试试这个:
Every control in wpf inherits properties from its parent. Since the TabItem's color was black, its child
textblock
was also of black color. Now since you've changed the entire TabItem's foreground color to green, all its children will inherit it.Here you can set your TabItem.Header's or its contents' foreground to green, so that it will not affect other contents in the TabItem. Else you can invert the solution.
Else Try this:
这是一个实用的解决方案,假设黑色将是 TabItem 中 TextBlock 等可接受的前景色。
首先,因为我使用 Canvas 作为 TabItem 的主体,所以我制作了如下自定义样式:
然后,TabItem(恰好使用 Canvas 作为容器)看起来像这样,其中 TabItem 前景设置为绿色,但是画布的样式为前景黑色:
如果您使用网格而不是画布,它也同样有效。只需将样式的 TargetType 设置为 x:Type Grid 即可。
Here is a practical solution which assumes that black will be an acceptable foreground color for TextBlocks etc. in your TabItem.
First, because I use a Canvas for the body of my TabItem, I made a custom style like this:
Then, the TabItem (which happens to use a Canvas as container) looks like this, where the TabItem Foreground is set to Green, but the Canvas is styled to Foreground black:
If you're using a Grid instead of a Canvas, it works just as well. Just make your style's TargetType as x:Type Grid.