Silverlight MVVM设置控件焦点

     silverlight开发中设置某个控件的焦点,如果是在code behind 情况下可以通过直接设定某个控件的focus()方法就可以实现。但是如果我们是用MVVM模式下通过绑定来实现呢?比如这样一个场景,一个登陆页面,需要设定登录名控件TboxLogin(TextBox)默认具有焦点。通过研究发现,TextBox并没有设置Focus的依赖属性,因此,直接绑定是不能实现的,我们只能通过其他方法来实现。

   在Silverlight中有个System.Windows.Interactivity.dll的类库,专门用来处理Silverlight交互方面的功能,我们可以通过其中的Behavior来实现这里的需求。比如定义一个TextBoxFocusBehavior的类,让它继承自Behavior<TextBox>并在其中定义一个附加属性IsFocused,然后通过该属性的变化来设定TextBox 是否有焦点。  

TextBoxFocusBehavior
 1  public class TextBoxFocusBehavior : Behavior<TextBox>
 2     { 
 3         public static bool GetIsFocused(DependencyObject obj)
 4         {
 5             return (bool)obj.GetValue(IsFocusedProperty);
 6         }
 7 
 8         public static void SetIsFocused(DependencyObject obj, bool value)
 9         {
10             obj.SetValue(IsFocusedProperty, value);
11         } 
12         public static readonly DependencyProperty IsFocusedProperty =
13             DependencyProperty.RegisterAttached("IsFocused", typeof(bool),
14             typeof(TextBoxFocusBehavior), new PropertyMetadata((s, e) =>
15             {
16                 var textBox = s as TextBox;
17                 if (textBox != null && e.NewValue is bool && (bool)e.NewValue)
18                 {
19                     textBox.Focus();
20                 }
21             }));
22     }

定义好上面的类后,就可以在Xaml中通过绑定ViewModel中的某个bool属性到TextBox的IsFocused附加属性了,Xaml中处理类似: <TextBox Text="{Binding LoginName, Mode=TwoWay, UpdateSourceTrigger= PropertyChanged}"
                 loc:TextBoxFocusBehavior.IsFocused="{Binding IsFocused, Mode=TwoWay}" >
        </TextBox> 这样只要ViewModel中的IsFocused应属性变化了,就可以通知TextBox是否具有焦点。

延伸:这里我们处理的是TextBox的焦点设置,有可能我们之后还要设定PasswordBox或者RichTextbox等其他控件的焦点。因此,这里我们可以对这个Behavior进行抽象处理,这样具体某个类型的控件需要设定焦点行为时候,直接继承该抽象类就行了。实现如下:

ControlFocusBehavior
 1  public class ControlFocusBehavior<T> : Behavior<FrameworkElement> where T : Control
 2     {
 3         public static bool GetIsFocused(T obj)
 4         {
 5             return (bool)obj.GetValue(IsFocusedProperty);
 6         }
 7 
 8         public static void SetIsFocused(T obj, bool value)
 9         {
10             obj.SetValue(IsFocusedProperty, value);
11         }
12 
13         public static readonly DependencyProperty IsFocusedProperty =
14             DependencyProperty.RegisterAttached("IsFocused", typeof(bool),
15             typeof(ControlFocusBehavior<T>), new PropertyMetadata((obj, e) =>
16             {
17                 var element = obj as T;
18                 if (element != null && e.NewValue is bool && (bool)e.NewValue)
19                 {
20                     element.Focus();
21                 }
22             }));
23     }

有了上面的抽象类,这个时候我们就好办了,比如上面的TextBox需要焦点处理。直接通过该抽象类,实现一个TextBox的就行 

 public class TextBoxFocusBehavior : ControlFocusBehavior<TextBox>    {}

PasswordBox同样的: public class PasswordBoxFocusBehavior : ControlFocusBehavior<TextBox>    {}

这样就达到了我们的目的了。

备注:在Silverlight程序启动后,我们的第一个Xaml其实并没有获取到焦点,需要在启动的第一个Xaml页面中设定一行代码,让它默认得到焦点 HtmlPage.Plugin.Focus();

 

 

posted @ 2012-12-29 00:24  rpoplar  阅读(735)  评论(0编辑  收藏  举报