WPF - TabItem MouseOver not working as intended

2020-04-08 12:27发布

问题:

I have an issue with the IsMouveOver trigger with a TabItem Element.

When the mouse cursor is on a TabItem, its background color changes, which is what I want => It works. However the background color of the TabItem also changes whenever my mouse cursor is on an item inside the TabItem.

Here's the XAML related to the styling:

    <Style x:Key="SupTest" TargetType="{x:Type TabItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <Border Margin="2" Name="TabBorder" CornerRadius="6" BorderBrush="Transparent" Background="Transparent" 
                        BorderThickness="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <StackPanel Margin="12" Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                        <Rectangle Width="25" Height="25" Fill="Blue" HorizontalAlignment="Left" Margin="00,0,0,0"></Rectangle>
                        <ContentPresenter ContentSource="Header" VerticalAlignment="Center" 
                                          HorizontalAlignment="Stretch" Margin="10,0,0,0"></ContentPresenter>
                    </StackPanel>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Panel.ZIndex" Value="100" />
                        <Setter TargetName="TabBorder" Property="Background" Value="#FFDFDFDF" />
                        <Setter TargetName="TabBorder" Property="BorderThickness" Value="2" />
                        <Setter TargetName="TabBorder" Property="BorderBrush" Value="{DynamicResource WindowTitleColorBrush}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="TabBorder" Property="Background" Value="DarkRed" />
                        <Setter TargetName="TabBorder" Property="BorderBrush" Value="Black" />
                        <Setter Property="Foreground" Value="DarkGray" />
                    </Trigger>
                    <Trigger Property="Border.IsMouseOver" Value="True">
                        <Setter TargetName="TabBorder" Property="Background" Value="{DynamicResource WindowTitleColorBrush}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    </Style>

And the XAML code for the windows itself:

    <TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TabStripPlacement="Left"
                BorderThickness="1,0,0,0" BorderBrush="{DynamicResource WindowTitleColorBrush}">
        <TabItem Header="Item #1" Style="{StaticResource SupTest}">
             <Grid>
                <Button Content="Button" HorizontalAlignment="Left" Margin="10" VerticalAlignment="Top" Width="75"/>
            </Grid>
        <TabItem Header="Item #2" Style="{StaticResource SupTest}">
             <Grid>
                <Button Content="Button Teeest" HorizontalAlignment="Left" Margin="10" VerticalAlignment="Top" Width="75"/>
            </Grid>
        </TabItem>
    </TabControl>

With this code for example, the IsMouseOver of a TabItem is triggered when the mouse cursor is on the button it contains.

How to fix this? :P

Thanks for the help =)

回答1:

It does not work because Border as container takes all events, and MouseOver is not exception. If you want to ignore MouseOver event for some part (your inner part of the item) then just put inner item on top of wider item.

You can add Grid control beneath inner part and bind Trigger to its MouseOver event.

    <Border Margin="2" Name="TabBorder" CornerRadius="6" BorderBrush="Transparent" Background="Transparent" 
BorderThickness="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid>
    <Grid x:Name="gridMouseOver"/>
    <StackPanel Margin="12" Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <Rectangle Width="25" Height="25" Fill="Blue" HorizontalAlignment="Left" Margin="00,0,0,0"></Rectangle>
            <ContentPresenter ContentSource="Header" VerticalAlignment="Center" 
                    HorizontalAlignment="Stretch" Margin="10,0,0,0"></ContentPresenter>
        </StackPanel>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
    <Setter Property="Panel.ZIndex" Value="100" />
    <Setter TargetName="TabBorder" Property="Background" Value="#FFDFDFDF" />
    <Setter TargetName="TabBorder" Property="BorderThickness" Value="2" />
    <Setter TargetName="TabBorder" Property="BorderBrush" Value="{DynamicResource WindowTitleColorBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
    <Setter TargetName="TabBorder" Property="Background" Value="DarkRed" />
    <Setter TargetName="TabBorder" Property="BorderBrush" Value="Black" />
    <Setter Property="Foreground" Value="DarkGray" />
</Trigger>
<Trigger SourceName="gridMouseOver" Property="IsMouseOver" Value="True">
    <Setter TargetName="TabBorder" Property="Background" Value="{DynamicResource WindowTitleColorBrush}"/>
</Trigger>
</ControlTemplate.Triggers>


回答2:

bit of an old question but this has been troubling me all day....

<MultiDataTrigger.Conditions>
    <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true" />
    <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="false"/>
    <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}" Value="Top"/>
</MultiDataTrigger.Conditions>

This solved it for me

ignores the mouse over for the active tab

Hope this helps any one who has this problem