Konrad Viltersten
Konrad Viltersten

Reputation: 39068

TabItem fires FocusGot event when clicking on any control placed in it

I'm getting a hit on the method below as soon as I click the tab in question.

private void Tab1_GotFocus(Object sender, RoutedEventArgs eventArgs) 
{
  DoStuff();
}

However, I noticed that when I click any control placed on that tab, the event is fired too. Can I turn off the behavior? Can I detect if the event is fired "for real" or "just for fun", so to speak?

A small voice in my head tells me to compare what's being gotten in focus with what's being lost and if it's the same (or childly) component, skip the method. But that sounds weird...

private void Tab1_GotFocus(Object sender, RoutedEventArgs eventArgs)
{
  if(sender == eventArgs.OriginalSource)
    DoStuff();
}

Instead, I'm trying to work with the following.

private void TabControl_OnSelectionChanged(Object sender, SelectionChangedEventArgs eventArgs)
{
  ...
}

However, it's being fired and then re-fired due to something I do inside it. (I update the data grid contained on the one of the tabs upon the selection being changed. I suspect that sorting and/or filtering might cause those issues.)

Is this the right approach?

Upvotes: 1

Views: 2151

Answers (1)

dkozl
dkozl

Reputation: 33364

As mentioned in comments both UIElement.GotFocus and Selector.SelectionChanged are bubbling events which means that they will bubble up the visual tree and event handler will be triggered on a parent control for every child that raises this routed event. In case of GotFocus event it will be every UIElement and SelectionChanged will be triggered by every Selector control like ComboBox, ListBox, ListView or DataGrid.

You should still be able to handle SelectionChanged event like that just ignore every call where e.OriginalSource is not TabControl

private void TabControl_OnSelectionChanged(
  Object sender, SelectionChangedEventArgs eventArgs)
{
  var tabControl = eventArgs.OriginalSource as TabControl;
  if (tabControl != null)
    SolveAllProblems();
}

It's not fool proof and if you will have TabControl as child of TabControl it will still be triggered. In case it's only supposed to handle a specific tab, the following will do just fine.

private void TabControl_OnSelectionChanged(
  Object sender, SelectionChangedEventArgs eventArgs)
{
  if ((eventArgs.OriginalSource as TabControl)?.SelectedItem == TabToBeHandled)
    SolveAllProblems();
}

Note the cool new addition to .NET - the surprised dot (coalescent operator).

Upvotes: 4

Related Questions