ScrollViewer中元素焦点丢失问题

原文http://www.cnblogs.com/xiaoxueliang/archive/2010/08/08/1795128.html

   Silverlight中的焦点常用设置控件的外观和键盘操作。在做模板控件时,我们常常需要捕获元素焦点状态。根据元素是否具有焦点来呈现不同的视觉状态。最近的项目中碰到一个奇怪现象:我将一个模板控件在ScrollViewer中,在MouseLeftButtonDown调用Focus时,Focus()返回true,控件会得到焦点,然而瞬间又失去焦点,导致控件无法正常获取焦点。如果将该控件放在Canvas、Grid中都能正确的获取焦点,并显示焦点视觉效果。 下面是模板控件中的示意代码:

      

代码
复制代码
  public  TemplatedControl1()
        {
            
this .DefaultStyleKey  =  typeof (TemplatedControl1);
        }

        
public  bool  isFocused  =  false ;
        
public  bool  IsFocused
        {
            
get
            {
                
return  isFocused;

            }
            
set
            {
                
if  (isFocused  !=  value)
                {
                    isFocused 
=  value;
                    UpdateStates(
true );
                }
            }
        }

        
protected  override  void  OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            
base .OnMouseLeftButtonDown(e);
            Focus();
        }

        
protected  override  void  OnGotFocus(RoutedEventArgs e)
        {
            
base .OnGotFocus(e);
            isFocused 
=  true ;
            UpdateStates(
true );
        }

        
protected  override  void  OnLostFocus(RoutedEventArgs e)
        {
            
base .OnLostFocus(e);
            isFocused 
=  false ;
            UpdateStates(
true );
        }

        
private  void  UpdateStates( bool  useTransitions)
        {
            
if  (isFocused)
            {
                VisualStateManager.GoToState(
this " Focused " , useTransitions);
            }
            
else
            {
                VisualStateManager.GoToState(
this " Unfocused " , useTransitions);
            }
        }
复制代码


      这个问题让我觉得Silverlight的焦点不太稳定。进过观察发现,ScrollViewer通过获取MouseLeftButtonDown的路由事件,然后做了一些我们不知道的操作,导致控件失去了焦点。如何解决这个问题,这里提供两种思路:

     第一种:在模板控件的重载方法OnMouseLeftButtonDown中加上e.Handled = true。 这样就阻止了ScrollViewer获取点击事件。这种方法的弊端就是也停止了OnMouseLeftButtonDown的路由。

     第二种:在MouseLeftButtonUp中调用Focus()获取焦点,此方法调用在ScrollViewer发生作用之后,所以能正确的设置焦点状态。缺点是:如果模板控件已经有焦点时,点击控件,就会导致控件先失去焦点,然后在MouseLeftButtonUp事件中再得到焦点,形成无谓的视觉效果跳动。

 

      这样焦点的问题是可以解决,不过ScrollViewer在OnMouseLeftButtonDown事件中为什么会夺取去子元素的焦点,还是不得而知。

 

你可能感兴趣的:(scrollview)