TabItem 在单击放置在其中的任何控件时触发 FocusGot 事件

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

单击相关选项卡后,我立即使用了以下方法。

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

但是,我注意到当我单击位于该选项卡上的 任何 控件时,该事件也会被触发。我可以关闭该行为吗?我可以检测事件是否被触发 "for real" 或 "just for fun",可以这么说吗?

我脑海中的一个小声音告诉我比较关注的内容和丢失的内容,如果它是相同的(或幼稚的)组件,则跳过该方法。但这听起来很奇怪...

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

相反,我正在尝试使用以下内容。

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

但是,由于我在里面做了一些事情,它被解雇了然后又被解雇了。 (我在更改选择时更新了其中一个选项卡中包含的数据网格。我怀疑排序 and/or 过滤可能会导致这些问题。)

这是正确的方法吗?

如评论中所述,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 控制方式类似于 ComboBoxListBoxListViewDataGrid

您应该仍然能够像那样处理 SelectionChanged 事件,只需忽略每个 e.OriginalSource 不是 TabControl

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

它不是万无一失的,如果你将 TabControl 作为 TabControl 的 child,它仍然会被触发。如果它只应该处理一个特定的选项卡,下面的就可以了。

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

请注意 .NET 的新增功能 - 惊喜点(合并运算符)。