TabItem Header 作为标签看起来不同

TabItem Header looks different as a Label

我有一个 TabItem 并且之前在 object 中设置 Header 就像这样,

<TabItem x:Name="Checked_Out_Items" Header="Clients In Use" Height="40" LostFocus="Checked_Out_Items_LostFocus" GotFocus="Checked_Out_Items_GotFocus" BorderThickness="0" >

但是,我 运行 遇到了此选项卡没有 Click 事件的问题。我找到了一个解决方案,我们可以插入一个标签作为此处指定的 header, how to handle TabItem single click event in WPF?

但是,标签看起来与我需要的完全不同。这是 object 中定义的 Tab Header。

这是带有标签的样子

        <TabItem x:Name="Checked_Out_Items" Height="40" LostFocus="Checked_Out_Items_LostFocus" GotFocus="Checked_Out_Items_GotFocus" BorderThickness="0" >
            <TabItem.Header>
                <Label Content="Clients In Use" Height="40" MouseLeftButtonDown="Checked_Out_Items_Clicked" Width="171" />
            </TabItem.Header>

让我们稍微分开一下。

为了处理鼠标单击事件,需要准备一个控件来接收此事件,它需要实现一个处理程序,并且该处理程序必须实际接收该事件。在 TabItem 的情况下,鼠标单击事件由控件消耗,而不将事件释放给用户定义的侦听器。

TabItem 级别,最好的选择是处理 PreviewMouseLeftButtonDown 事件,但如果在 child 控件时不应该发生事件处理,则这不是一个选项有自己的处理功能。

所以另一个选择是在 MouseLeftButtonDown 事件到达 TabItem 之前处理它,这意味着在选项卡项的 child 控件中处理它。

如前所述,为了接收事件,控件需要准备好接收事件。这意味着,它需要 Background 而不是 null(可以是 Transparent)和 IsHitTestEnabled="True"(在大多数情况下是默认值)并且它必须实际处理事件。

对于展示,我使用 Red 而不是 Transparent 背景色。红色区域是捕获和处理鼠标点击的地方。

<TabItem Padding="0">
    <TabItem.Header>
        <Border Height="30" Width="50"
                Background="Red" MouseLeftButtonDown="Item_MouseLeftButtonDown">
            <ContentPresenter
                VerticalAlignment="Center" HorizontalAlignment="Center"
                Content="T2"/>
        </Border>
    </TabItem.Header>
    Test Content 2
</TabItem>

或者,为了更好地分离 header 内容和点击处理,可以使用 HeaderTemplate

<TabItem Header="T3" Padding="0">
    <TabItem.HeaderTemplate>
        <DataTemplate>
            <Border MinHeight="30" MinWidth="50"
                    Background="Red" MouseLeftButtonDown="Item_MouseLeftButtonDown">
                <ContentPresenter
                    VerticalAlignment="Center" HorizontalAlignment="Center"
                    Content="{Binding}"/>
            </Border>
        </DataTemplate>
    </TabItem.HeaderTemplate>
    Test Content 3
</TabItem>

任何依赖 child 控件的方法的问题是,TabItem 仍然有一个边框,如果用户单击该边框,则单击将在 child 控件和选项卡将在不执行单击处理程序的情况下被选中。

因此,处理选项卡更改(不是点击!)的另一种方法是处理 TabControl.SelectionChanged 事件并过滤实际上源自 TabControl 而不是某些内部内容元素的事件.

private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.Source == sender)
    {
        // this selection change is actually issued because of a tab change
    }
}

我刚刚意识到的另一件事:可以在 TabItem.PreviewMouseLeftButtonDown 中使用相同的条件来过滤对 tabitem header 的点击与来自内容区域的点击事件。

编辑:

Label 看起来不同的原因是,TabItem 的字体样式处于活动状态,而 Label 正在使用其某些内部样式,忽略了 TabItem风格。