【问题标题】:TabItem Header looks different as a LabelTabItem Header 看起来与 Label 不同
【发布时间】:2016-11-28 17:57:39
【问题描述】:

我有一个 TabItem,之前在对象中设置了 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 事件的问题。我找到了一个解决方案,我们可以在其中插入一个标签作为此处指定的标题, how to handle TabItem single click event in WPF?

但是,标签看起来不像我需要的。这是对象内部定义的选项卡标题。

这是标签的样子

        <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>

【问题讨论】:

  • 当您将标签放在应用程序的其他位置时,它会如何寻找您?也许它只是在应用资源某处定义的默认样式。
  • @grek40 它们看起来一样,所以它必须是默认样式。
  • 点击主题的另一个旁注:只需在TabItem 上收听PreviewMouseLeftButtonDown,因为与MouseLeftButtonDown 事件不同,它实际上会被触发;)
  • 使用ContentControl代替标签,或者将Label的样式设置为没有BasedOn属性的空样式。
  • @TalenKylon 抱歉,有一点误解。没有Label 的文本是特殊样式的,该样式不会转移到标签上。

标签: wpf tabitem


【解决方案1】:

让我们把关注点分开一点。

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

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

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

如前所述,为了接收事件,控件需要准备好接收事件。这意味着,它需要 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>

或者,为了更好地分离标题内容和点击处理,可以使用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>

任何依赖子控件的方法的问题是,TabItem 的边框仍然存在,如果用户单击该边框,则单击将在子控件之外,并且选项卡将被选中执行点击处理程序。

因此,处理选项卡更改(不是点击!)的另一种方法是处理 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 标题的点击与来自内容区域的点击事件。

编辑:

Label 看起来不同的原因是,TabItem 的字体样式是活动的,而Label 正在使用它的一些内部样式,而忽略了TabItem 样式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多