转载请注明出处:http://www.cnblogs.com/ainijiutian
最近在silverlight项目使用Telerik的控件,遇到一个问题。就是使用RadBusyIndicator,当IsBusy = false时,其内的控件(以TextBox为例)的焦点会丢失。IsBusy绑定的是ViewModel的IsBusy属性,Button点击时调用ViewModel的异步耗时方法,耗时方法结束时设置IsBusy = false,再调用回调函数。在回调函数调用txtInput.Focus()。
>
/>
/>
>
看样子是没什么问题的,但是实际情况是文本框不会获取到焦点。经过跟踪也发现txtInput.Focus()返回false。
正文
在谷歌狂搜,才发现RadBusyIndicator的IsBusy不靠谱,IsBusyIndicationVisible才是好孩子。反编译也证明了这点,IsBusy设置为false时,在 AnimationManager.Play函数的回调里设置IsBusyIndicationVisible=false。不过IsBusyIndicationVisible定义的是private set,程序里不太好监控。官方论坛有一种解决方案,是定义一个有附加属性的类,然后在文本框上增加local:Helper.EnsureFocus="{Binding IsBusyIndicationVisible, ElementName=rbiBusy}"。
class Helper
2: {
void OnEnsureFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
4: {
bool)e.NewValue)
6: {
as Control).Focus();
8: }
9: }
10:
bool GetEnsureFocus(DependencyObject obj)
12: {
bool)obj.GetValue(EnsureFocusProperty);
14: }
15:
value)
17: {
value);
19: }
20:
// Using a DependencyProperty as the backing store for EnsureFocus. This enables animation, styling, binding, etc...
readonly DependencyProperty EnsureFocusProperty =
new PropertyMetadata(OnEnsureFocusChanged));
24: }
不过发现不能通用到其他场景。后来又发现一牛人2009年的帖子,才最终解决。
结语
整理如下。有兴趣可以做成扩展方法。
string propertyName, PropertyChangedCallback callback)
2: {
http://www.cnblogs.com/ainijiutian
new System.Windows.PropertyMetadata(callback));
5: element.SetBinding(prop, b);
6: }
使用
, rbiBusy, (d, a) =>
2: {
bool)a.NewValue)
4: {
5: txtInput.Focus();
6: }
7: });