How do I prevent a child TabControl from inheriting the parent TabControl's SelectionChanged event handler?

Jason Etherton 1 Reputation point
2021-05-18T10:17:03.517+00:00

Hello World,

I'm fairly new to WPF and am trying to embed a TabControl within another TabControl. My issue is that the child TC (with NO SelectionChanged handler defined) is triggering the parent's SelectionChanged handler.

I don't care about the child's TabControl selection, and although I could just add in a new handler for the child with e.handled = true, this seems like a workaround (albeit small) for inherited behaviour that I neither configured nor wanted.

Am I missing something?

I can't set SelectionChanged="" or SelectionChanged="null" - Is there a "proper" way to avoid event handler inheritance in XAML?

Using the snippets below, the parent's handler is triggered by changing the child tab selection.

XAML:

<TabControl Name="ParentTab" SelectionChanged="ParentTabSelectionChangedHandler">
    <TabItem Header="TabItem1" />
    <TabItem Header="TabItem2">
        <TabControl Name="ChildTab" TabStripPlacement="Left">
            <TabItem Header="TabItem3" />
            <TabItem Header="TabItem4" />
        </TabControl>
    </TabItem>
</TabControl>

C#

private void ParentTabSelectionChangedHandler(object sender, SelectionChangedEventArgs e)
{
    Debug.Print("Sent from " + (sender as TabControl).Name);    
    e.Handled = true;
}

In visual form

MainWindow
└─ ParentTab (ParentTabSelectionChangedHandler)
   ├─ TabItem1
   └─ TabItem2
      └─ ChildTab
         ├─ TabItem3
         └─ TabItem4

So switching between TabItem1 and TabItem2 triggers the event handler, as expected. Switching between TabItem3 and TabItem4 also triggers the child's inherited version of the parent's event handler. This is prevented from bubbling further by the e.handled = true line, but my issue is that the parent's tab selection does not change.

It just seems strange as this strategy forces any nested Selectors uninterested in the top level event to explicitly catch events just to ignore them. Depending upon the application, this could be many lines of code put in place explicitly to do nothing.

In the above example, selecting TabItem3 triggers ParentTabSelectionChangedHandler even though the parent TabControl (ParentTab) does not have its selection changed (it remains on TabItem2), and ChildTab has no SelectionChanged event handler defined.

Please help, internet - the act of adding lines of code to ignore behaviour I haven't configured makes me think I'm doing something wrong.

Developer technologies | Windows Presentation Foundation
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. DaisyTian-1203 11,646 Reputation points
    2021-05-19T02:56:24.783+00:00

    Selector.SelectionChanged Event occurs when the selection of a Selector changes. The ChildTab is included in ParentTab Selector , ChildTab selectionChanged causes ParentTab to has a selectionChanged.
    I make some update to your code and use MouseLeftButtonDown to replace selectionChanged. Below is my code for you:
    XAML code:

    <TabControl>  
                <TabControl.ItemContainerStyle>  
                    <Style TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">  
                        <Setter Property="HeaderTemplate">  
                            <Setter.Value>  
                                <DataTemplate>  
                                    <Label Content="{Binding}" Name="ParentTab">  
                                        <Label.Style>  
                                            <Style TargetType="Label">  
                                                <EventSetter Event="MouseLeftButtonDown" Handler="Label_MouseLeftButtonDown"/>  
                                            </Style>  
                                        </Label.Style>  
                                    </Label>  
                                </DataTemplate>  
                            </Setter.Value>  
                        </Setter>  
                    </Style>  
                </TabControl.ItemContainerStyle>  
                <TabItem Header="TabItem1" />  
                <TabItem Header="TabItem2">  
                    <TabControl Name="ChildTab" TabStripPlacement="Left">  
                        <TabItem Header="TabItem3" />  
                        <TabItem Header="TabItem4" />  
                    </TabControl>  
                </TabItem>  
            </TabControl>  
    

    C# code is:

     private void Label_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)  
            {  
                Debug.Print("\n ************ Sent from " + (sender as Label).Name);  
            }  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.