• [Silverlight]监听指定控件(FrameworkElement)的依赖属性(DependencyProperty)的更改


    前言

    转载请注明出处:http://www.cnblogs.com/ainijiutian

    最近在silverlight项目使用Telerik的控件,遇到一个问题。就是使用RadBusyIndicator,当IsBusy = false时,其内的控件(以TextBox为例)的焦点会丢失。IsBusy绑定的是ViewModel的IsBusy属性,Button点击时调用ViewModel的异步耗时方法,耗时方法结束时设置IsBusy = false,再调用回调函数。在回调函数调用txtInput.Focus()。

       1: <telerik:RadBusyIndicator x:Name="rbiBusy" IsBusy="{Binding IsBusy}">
       2:     <telerik:RadButton Content="Button" Name="button1" Click="button1_Click" />
       3:     <TextBox x:Name="txtInput" />
       4: </telerik:RadBusyIndicator>

    看样子是没什么问题的,但是实际情况是文本框不会获取到焦点。经过跟踪也发现txtInput.Focus()返回false。

    正文

    在谷歌狂搜,才发现RadBusyIndicator的IsBusy不靠谱,IsBusyIndicationVisible才是好孩子。反编译也证明了这点,IsBusy设置为false时,在  AnimationManager.Play函数的回调里设置IsBusyIndicationVisible=false。不过IsBusyIndicationVisible定义的是private set,程序里不太好监控。官方论坛有一种解决方案,是定义一个有附加属性的类,然后在文本框上增加local:Helper.EnsureFocus="{Binding IsBusyIndicationVisible, ElementName=rbiBusy}"。

       1: public class Helper
       2: {
       3:     private static void OnEnsureFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
       4:     {
       5:         if (!(bool)e.NewValue)
       6:         {
       7:             (d as Control).Focus();
       8:         }
       9:     }
      10:  
      11:     public static bool GetEnsureFocus(DependencyObject obj)
      12:     {
      13:         return (bool)obj.GetValue(EnsureFocusProperty);
      14:     }
      15:  
      16:     public static void SetEnsureFocus(DependencyObject obj, bool value)
      17:     {
      18:         obj.SetValue(EnsureFocusProperty, value);
      19:     }
      20:  
      21:     // Using a DependencyProperty as the backing store for EnsureFocus.  This enables animation, styling, binding, etc...
      22:     public static readonly DependencyProperty EnsureFocusProperty =
      23:     DependencyProperty.RegisterAttached("EnsureFocus", typeof(bool), typeof(Helper), new PropertyMetadata(OnEnsureFocusChanged));
      24: }

    不过发现不能通用到其他场景。后来又发现一牛人2009年的帖子,才最终解决。

    结语

    整理如下。有兴趣可以做成扩展方法。

       1: public void ListenPropertyChanged(FrameworkElement element, string propertyName, PropertyChangedCallback callback)
       2: {
       3:     Binding b = new Binding(propertyName) { Source = element }; //http://www.cnblogs.com/ainijiutian
       4:     var prop = System.Windows.DependencyProperty.RegisterAttached("ListenAttached" + propertyName, typeof(object), typeof(FrameworkElement), new System.Windows.PropertyMetadata(callback));
       5:     element.SetBinding(prop, b);
       6: }

    使用

       1: ListenPropertyChanged("IsBusyIndicationVisible", rbiBusy, (d, a) =>
       2: {
       3:     if (!(bool)a.NewValue)
       4:     {
       5:         txtInput.Focus();
       6:     }
       7: });
  • 相关阅读:
    【006期】JavaSE面试题(六):泛型
    【005期】JavaSE面试题(五):String类
    【004期】JavaSE面试题(四):JavaSE语法(3)
    【003期】JavaSE面试题(三):JavaSE语法(1)
    【002期】JavaSE面试题(二):基本数据类型与访问修饰符
    【001期】 | JavaSE面试题(一):面向对象
    【000期】Java最全面试题库思维导图
    LeetCode 1. 两数之和(python3)实现
    虚拟网络学习笔记一:Linux虚拟网络
    快速排序(python实现)
  • 原文地址:https://www.cnblogs.com/ainijiutian/p/3158468.html
Copyright © 2020-2023  润新知