silverlight开发中设置某个控件的焦点,如果是在code behind 情况下可以通过直接设定某个控件的focus()方法就可以实现。但是如果我们是用MVVM模式下通过绑定来实现呢?比如这样一个场景,一个登陆页面,需要设定登录名控件TboxLogin(TextBox)默认具有焦点。通过研究发现,TextBox并没有设置Focus的依赖属性,因此,直接绑定是不能实现的,我们只能通过其他方法来实现。
在Silverlight中有个System.Windows.Interactivity.dll的类库,专门用来处理Silverlight交互方面的功能,我们可以通过其中的Behavior来实现这里的需求。比如定义一个TextBoxFocusBehavior的类,让它继承自Behavior<TextBox>并在其中定义一个附加属性IsFocused,然后通过该属性的变化来设定TextBox 是否有焦点。
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进行抽象处理,这样具体某个类型的控件需要设定焦点行为时候,直接继承该抽象类就行了。实现如下:
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();