WPF中PreviewMouseDownEvent的系统处理:TabItem的PreviewMouseDown 事件弹框后不切换的问题调查


背景:
UI中有一个TabControl, 包含2个TabItem,当切换到别的TabItem时可能弹框然后根据逻辑判断是否跳转过去。
然后我就做了这样一个demo:

xaml:

< UserControl
      xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns : x   ="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns : d   ="http://schemas.microsoft.com/expression/blend/2008"
      xmlns : mc   ="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns : i   ="http://schemas.microsoft.com/expression/2010/interactivity"
      xmlns : ic   ="http://schemas.microsoft.com/expression/2010/interactions"
      xmlns : local   ="clr-namespace:WpfApplication4"
      mc : Ignorable   ="d"
      x : Class   ="WpfApplication4.MainView"
      d : DesignWidth   ="640"
      d : DesignHeight   ="480" >

      < Grid
          x : Name   ="LayoutRoot" >
          < TabControl
              x : Name   ="tbcTest"
              SelectionChanged ="TabControl_SelectionChanged" >
              < TabItem
                  x : Name   ="tiItem1"
                  Header ="TabItem1" >
                  < Grid
                      Background ="#FFE5E5E5" >
                      < Button
                          Content ="Button"
                          VerticalAlignment ="Top"
                          Margin ="73,197,142,0" />
                  </ Grid >
              </ TabItem >
              < TabItem
                  x : Name   ="tiItem2"
                  Header ="TabItem2"
                  PreviewMouseLeftButtonDown ="TabItem_PreviewMouseLeftButtonDown" >
                  < Grid
                      Background ="#FFE5E5E5" >
                      < RadioButton
                          Content ="RadioButton"
                          HorizontalAlignment ="Left"
                          VerticalAlignment ="Top" />
                  </ Grid >
              </ TabItem >
          </ TabControl >
      </ Grid >
</ UserControl >


C# code:

using   System   . Windows ;
using   System   . Windows .   Controls ;

namespace   WpfApplication4
{
      public   partial   class   MainView   :   UserControl
    {
          public   MainView   ()
        {
              // Required to initialize variables
              InitializeComponent ();
        }

          private   void   TabControl_SelectionChanged (   object   sender   ,   System . Windows   . Controls .   SelectionChangedEventArgs   e   )
        {
              System . Diagnostics   . Debug .   WriteLine ( "SelectionChanged..."   );
        }

          private   void   TabItem_PreviewMouseLeftButtonDown ( object   sender ,   System . Windows   . Input .   MouseButtonEventArgs   e   )
        {
              System . Diagnostics   . Debug .   WriteLine ( "PreviewMouseLeftButtonDown"   );

                  MessageBox . Show   ( "Test Modal Window" );
        }
    }
}


问题来了:
当点击第2个tabItem弹框后,tabControl并没有切换过去。

原因:
通过snoop的event分析后, 发现区别在于当弹框后焦点在Window上而不是TabItem上。 
(1)没有弹messagebox的事件
(2)弹messagebox后的事件


解决办法:
很简单,不需要指定TabControl的SelectedItem, 不需要RaiseEvent。只需在MessageBox之后调用Focus()。

private   void   TabItem_PreviewMouseLeftButtonDown ( object   sender ,   System . Windows   . Input .   MouseButtonEventArgs   e   )
        {
              System . Diagnostics   . Debug .   WriteLine ( "PreviewMouseLeftButtonDown"   );

              if   ( _isPopupMsgBox   )
            {
                  MessageBox . Show   ( "Test Modal Window" );
            }

              if   ( _isPopupMsgBox   )
            {
                  var   tabItem   =   sender   as   TabItem   ;
                  if   ( tabItem   !=   null )
                {
                      //当在当前的界面上弹出二级界面再次关闭后,
                      //焦点默认在当前窗体上,导致后续MouseDown事件并没有在TabItem上生效。
                    tabItem.Focus();
                }
            }
        }

你可能感兴趣的:(WPF,focus,ModalDialog,routeEvent)