C# WPF 样式 tabitem 文本前景触发,如 IsEnabled、IsMouseOver 等

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1130116/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 08:54:02  来源:igfitidea点击:

WPF styling tabitem text foreground upon trigger such as IsEnabled, IsMouseOver, etc

c#wpftabcontrolstylingtabitem

提问by

I'm trying to change the foreground text colour of a WPF tab item's header textblock using triggers. This works fine for most (simpler) scenarios but not when TextBlocks have been globally styled.

我正在尝试使用触发器更改 WPF 选项卡项的标题文本块的前景色文本颜色。这适用于大多数(更简单的)场景,但不适用于全局样式的 TextBlock。

So this simple "mouse over" trigger would work in terms of changing the foreground color:

所以这个简单的“鼠标悬停”触发器可以改变前景色:

<Style x:Key="testTabItemStyle1" TargetType="{x:Type TabItem}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
   <Setter.Value>
     <ControlTemplate TargetType="{x:Type TabItem}">
       <Grid SnapsToDevicePixels="true">
         <Border x:Name="Bd" Background="White" BorderBrush="Gray" BorderThickness="1,1,1,0">
            <ContentPresenter HorizontalAlignment="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" x:Name="Content" VerticalAlignment="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" ContentSource="Header"/>
         </Border>
       </Grid>
       <ControlTemplate.Triggers>
         <Trigger Property="IsMouseOver" Value="true">
           <Setter Property="Background" TargetName="Bd" Value="Black"/>
           <Setter Property="Foreground" Value="False"/>
         </Trigger>
       </ControlTemplate.Triggers>
     </ControlTemplate>
   </Setter.Value>
</Setter>
</Style>

The problem is that when TextBlocks are globally styled in App.xaml (for maintaining a consistent look), the foreground does not change, but retains the globally styled foreground color. This is how my TextBlocks are styled:

问题在于,当在 App.xaml 中全局设置 TextBlocks 样式时(为了保持一致的外观),前景不会改变,但会保留全局样式的前景色。这是我的 TextBlocks 的样式:

    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="FontFamily" Value="Arial"/>
        <Setter Property="Foreground" Value="Brown"/>
        <Setter Property="Margin" Value="4,0,4,0"/>
        <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
        <Setter Property="TextWrapping" Value="NoWrap"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
    </Style>

So my question is shouldn't the explicitly defined style assignment (in TabItem's trigger) have precedence? More importantly, how do I work around this without assigning styles to all my textblocks individually but having the TabItem textblock change color as expected?

所以我的问题是明确定义的样式分配(在 TabItem 的触发器中)不应该优先吗?更重要的是,如何在不单独为所有文本块分配样式但让 TabItem 文本块按预期更改颜色的情况下解决此问题?

Many thanks

非常感谢

NT

新台币

回答by Kent Boogaart

Works for me. Just had to change this:

为我工作。只需要改变这个:

<Setter Property="Foreground" Value="False"/>

to this:

对此:

<Setter Property="Foreground" Value="White"/>

回答by Kenan E. K.

You are setting the foreground color of a TabItem to Red, not the TextBlock. Maybe the TextBox style is not inherited from TabItem because user set implicit styles have precedence over trigger setters.

您将 TabItem 的前景色设置为红色,而不是 TextBlock。也许 TextBox 样式不是从 TabItem 继承的,因为用户设置的隐式样式优先于触发器设置器。

Try adding a binding to the TextBlock's parent TabItem Foreground property.

尝试将绑定添加到 TextBlock 的父 TabItem Foreground 属性。

EDIT

编辑

Like this

像这样

Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}, AncestorLevel=1}, Path=Foreground}"

回答by Kenan E. K.

What I meant was this:

我的意思是这样的:

<TabItem Header="Summary" x:Name="TabSummary" IsSelected="True" Style="{DynamicResource testTabItemStyle1}">
     <Border x:Name="TabSummaryBody" Margin="-5,-5,-5,-5">
             <StackPanel Margin="0,30,0,0" HorizontalAlignment="Center">
                   <TextBlock Text="Please select a document using the tree view on your right to show its properties." 
                              FontSize="16"
                              Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}, AncestorLevel=1}, Path=Foreground}"/>
             </StackPanel>
     </Border>
</TabItem>

Binding finds the parent TabItem and binds to its Foreground property.

绑定找到父 TabItem 并绑定到它的 Foreground 属性。

回答by Kenan E. K.

Many thanks for your help, you successfully steered me to the right direction.

非常感谢您的帮助,您成功地将我引向了正确的方向。

My intention was to alter the TabItem's text (Created by WPF's ContentPresenter) as opposed to the TextBlock within the tab which is declared in XAML and can easily change colour.

我的目的是改变 TabItem 的文本(由 WPF 的 ContentPresenter 创建),而不是在 XAML 中声明并且可以轻松更改颜色的选项卡中的 TextBlock。

The problem was with the global style taking precedence. And as the TextBlock is created by WPF rather than declared by me, I could not access it.

问题在于全局样式优先。由于 TextBlock 是由 WPF 创建的,而不是由我声明的,因此我无法访问它。

The solution was to specify the ContentPresenter Resources, as such:

解决方案是指定 ContentPresenter 资源,如下所示:

<ControlTemplate TargetType="{x:Type TabItem}">
 <Grid SnapsToDevicePixels="true">
  <Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Padding="{TemplateBinding Padding}">
   <ContentPresenter HorizontalAlignment="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" x:Name="Content" VerticalAlignment="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ContentSource="Header" RecognizesAccessKey="True">
   <ContentPresenter.Resources>
    <Style TargetType="{x:Type TextBlock}">
         <Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}"/>
    </Style>
   </ContentPresenter.Resources>
  </ContentPresenter>
  </Border>
 </Grid>

As you can see I have set the TextBlock style within the ContentPresenter resources. So obviously now any TextBlocks within the ContentPresenter shall use the parent's Foreground property and this will take precedence due to value coercion, solving my problem.

如您所见,我在 ContentPresenter 资源中设置了 TextBlock 样式。所以显然现在 ContentPresenter 中的任何 TextBlocks 都应该使用父级的 Foreground 属性,由于值强制,这将优先,解决我的问题。

Many thanks to all,

非常感谢大家,

NT

新台币