How to make only the header of the tabitem respond to the mouse event
I'm trying to make only the header of the TabItem send an event.
So far I have my xaml...
<TabControl>
<TabItem Header="tab 1">
Any text
</TabItem>
开发者_运维技巧 <TabItem Header="tab 2">
<TextBox>blah</TextBox>
</TabItem>
<TabControl.Resources>
<Style TargetType="TabItem">
<EventSetter Event="MouseDoubleClick" Handler="TabItemMouseDoubleClick"/>
</Style>
</TabControl.Resources>
</TabControl>
...and my event handler...
void TabItemMouseDoubleClick(object sender, MouseButtonEventArgs e)
{}
Now, when double clicking the tab item header the event fires, when clicking the tab item content area it doesn't fire (which is what I want), but when I put a text box in the TabItem, the event fires upon double clicking the textbox. I'm trying to get only the header of the TabItem to fire the event - any ideas?
What you're seeing is the effect of WPF's bubbling event model whereby events that happen in the children usually bubble up to the parent.
What you'll probably need to do is check the Source, or possibly the OriginalSource properties of the MouseButtonEventArgs, and only respond to events that are coming from TabItem types.
Another thing to try is checking the IsMouseDirectlyOver property which should return false if the mouse is inside the bounds of the parent, but is actually over a child element.
You might try setting IsHitTestVisible on, say, the TextBox in the tab item, but you would probably find that has undesirable side-effects, like not changing the selected tab when you click on the text.
You can get the behaviour you want by using a HeaderTemplate as follows (this is very basic so you will need to fix it up to sort out the heights of the label...etc). Just replace your current eventsetter with this setter:
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<Label Content={Binding}>
<Label.Style>
<Style TargetType="Label">
<EventSetter Event="MouseDoubleClick" Handler="TabItemMouseDoubleClick"/>
</Style>
</Label.Style>
</Label>
</DataTemplate>
</Setter.Value>
</Setter>
TabItem MouseDoubleClick event:
private void TabOnMouseDoubleClick(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
var tabItem = (sender as TabItem);
var mo = (tabItem.Content as UIElement).IsMouseOver;
if (!mo)
{
//Here you know you are working with header
}
}
I have the same need as the original question, but for one reason and another I don't want to delve into XAML to get this working ... so this quick'n'dirty code-only solution worked well for me:
void TabItemMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Point point = e.GetPosition(tabItem);
if (point.Y > 32)
{
// Click was below the tab header
// Note: 32 refers to the height of the tab header in pixels.
return;
}
// handle the double-click on the header here ...
// ...
}
For others, the final xaml to get the tabItems header only sending the event is...
<TabControl>
<TabItem Header="tab 1">
Any text
</TabItem>
<TabItem Header="tab 2">
<TextBox>blah</TextBox>
</TabItem>
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<Label Content="{Binding}">
<Label.Style>
<Style TargetType="Label">
<EventSetter Event="MouseDoubleClick" Handler="TabItemMouseDoubleClick"/>
</Style>
</Label.Style>
</Label>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
</TabControl>
精彩评论