惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
G
Google Developers Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
L
LangChain Blog
云风的 BLOG
云风的 BLOG
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
P
Proofpoint News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
小众软件
小众软件
WordPress大学
WordPress大学
A
About on SuperTechFans
大猫的无限游戏
大猫的无限游戏
C
Check Point Blog
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
美团技术团队
Jina AI
Jina AI
T
Tailwind CSS Blog
Google DeepMind News
Google DeepMind News
D
Docker

博客园 - 彭旭

VNC远程Gnome图形桌面(openEuler 20.03 LTS系统) [WPF]控件应用多个样式 [ASP.NET MVC] Real-time之HTML5 服务器发送事件(server-sent event) [WCF]DomainServices客户端操作异常处理 [Silverlight]键盘钩子KeyboardHook [Chrome扩展]屏蔽Google搜索结果重定向 Linq Distinct扩展 [Winform/C#]点击工作区域移动窗体 [WinForm] C#避免Panel(ScrollableControl)的子控件获取焦点时滚动条自动滚动 C#远程连接Oracle数据库(不安装客户端) RichTextBox.MouseWheel事件控制父控件Panel的内容滚动 ID3v1信息结构(MP3文件)的读取、修改(C#) 在线编辑Office文件 SQL优化 将自然数分解为若干连续的自然数 小写金额转换为大写金额 大数阶乘 查看文件夹大小及占用空间 VS2005开发WAP网站初识 - 彭旭 - 博客园
[Silverlight]监听指定控件(FrameworkElement)的依赖属性(Dep...
彭旭 · 2013-06-27 · via 博客园 - 彭旭

前言

转载请注明出处: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: });