上一篇我们提到希望建立一个通用的Command绑定,本篇就这个问题来和各位进行讨论。也希望各位能指出不足,提出改进的建议。

  我希望最终实现的效果如下图所示,可以给任何一个Control绑定Command,通过提供EventName来区分不同的事件,同时由Parameter来绑定需要传递的参数。

  同样,这里的local指的是CommandBinder类所在的命名空间。

<Rectangle Width="100" Height="100" Fill="Red" local:CommandBinder.Command="{Binding ViewModel.MouseLeftDownCommand, ElementName=window}"local:CommandBinder.EventName="MouseLeftButtonDown"local:CommandBinder.Parameter="{Binding RelativeSource={RelativeSource Self}}">
</Rectangle>

  很明显我们这里定义了3个附加属性。只是绑定的对象不同,EventName直接给了代表事件名的字符串,而Parameter没有绑定到ViewModel中的对象,而是通过ElementName绑定了我们希望传递的参数,这里是被点击的Rectangle。我们来看一下EventName和Parameter的定义。

        public static object GetParameter(DependencyObject obj){return (object)obj.GetValue(ParameterProperty);}public static void SetParameter(DependencyObject obj, object value){obj.SetValue(ParameterProperty, value);}// Using a DependencyProperty as the backing store for Parameter.  This enables animation, styling, binding, etc...public static readonly DependencyProperty ParameterProperty =DependencyProperty.RegisterAttached("Parameter", typeof(object), typeof(CommandBinder), new UIPropertyMetadata(null));public static string GetEventName(DependencyObject obj){return (string)obj.GetValue(EventNameProperty);}public static void SetEventName(DependencyObject obj, string value){obj.SetValue(EventNameProperty, value);}// Using a DependencyProperty as the backing store for EventName.  This enables animation, styling, binding, etc...public static readonly DependencyProperty EventNameProperty =DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(CommandBinder), new UIPropertyMetadata(null));

  附加属性的代码段快捷键是键入propa,再按2次Tab键,各位一试便知。对EventName和Parameter我们并没有做过多的处理,仅仅是希望他们以附加属性的形式能在XAML出现,并提供绑定的能力。

  真正取得绑定数据并关联Command.Execute方法的,仍然是CommandProperty:

        public static ICommand GetCommand(DependencyObject obj){return (ICommand)obj.GetValue(CommandProperty);}public static void SetCommand(DependencyObject obj, ICommand value){obj.SetValue(CommandProperty, value);}// Using a DependencyProperty as the backing store for CommonCommandBinder.  This enables animation, styling, binding, etc...public static readonly DependencyProperty CommandProperty =DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(CommandBinder), new PropertyMetadata(ChangedCallback));private static void ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e){FrameworkElement element = d as FrameworkElement;if (element != null){string eventName = element.GetValue(EventNameProperty) as string;if (eventName != null){EventInfo eventInfo = element.GetType().GetEvent(eventName);var handler = new MouseButtonEventHandler((sender, arg) => {object obj = element.GetValue(ParameterProperty);(e.NewValue as ICommand).Execute(obj);});var del = handler.GetInvocationList()[0];eventInfo.AddEventHandler(element, del);}}}

  在这里我们可以看到我们通过DependencyObject的GetValue方法,取到了绑定的EventName和Parameter。然后通过反射将EventInfo和具体的MouseButtonEventHandler关联起来。动态的通过字符串将具体的事件注册。

  但是这里有一个问题,针对事件不同的委托类型,比如这里的MouseButtonEventHandler,我没有办法创建一个通用的EventHandler。这就造成了针对不同的事件,我仍需要在这里写一个大大的switch case。这是这个本篇比较大的一个败笔。我暂时也没有更好的办法。在此也希望各位能给出好的建议。

  看到这里有人会说,WPF是有behavior的,即使是Silverlight也是可以用Blend来绑定Command的,不需要自己费力气去写这种不怎么好用的附加属性。确实是如此。本篇的起由还是对依赖属性的学习。在微软的Win8应用开发马拉松上,我曾苦恼过WinRT没有behavior如何绑定。这是一位胖胖的微软哥挺身而出以神一般的姿态出现,丢给我一个他写的CommandBinder,把依赖属性和数据绑定以全新的姿态展示在我面前,令我茅厕顿开啊!于是我就试图用WPF来重现该神奇的绑定。

  但是我却没有办法像Win8里一样实现如下图XAML的绑定,各位有兴趣可以在WPF试一试,或许可以使你对数据绑定有新的认识。

<Rectangle Width="100" Height="100" Fill="Red"  >
  <local:Common.CommonCommand><local:CommonCommand Command="{Binding Path=MouseLeftDownCommand}"EventName="MouseLeftButtonDown"Parameter="{Binding Path=Title}">    </local:CommonCommand>  </local:Common.CommonCommand></Rectangle>

  看似相似的绑定却始终无法在WPF中取到Parameter和Command的值。这里主要是期望把联系并不紧密的三个依赖属性EventNameProperty、ParameterProperty和CmmandProperty放置到一个叫做CommonCommand的类中,提高可读性和易用性。

  在这里CommonCommandProperty是作为附加属性出现的,所以他可以写成Rectangle的属性,而该属性是CommonCommand类型。EventNameProperty、ParameterProperty和CmmandProperty作为依赖属性存在于CommonCommand类中,而该类继承自DependencyObject。所以才能以上面的语法形式存在于XAML中。

  这里说了我没有成功获取到值,那么在通过Attached Property给控件绑定Command(三)中,我会提供一个替代的解决方案,敬请期待。

  同时也希望各位能对本篇提出意见和建议。

  这里给出本文相关的代码:

  3个附加属性的绑定形式:http://files.cnblogs.com/manupstairs/TestDPWpf.7z

  CommonCommand:http://files.cnblogs.com/manupstairs/TestDPWithParameter.zip

转载于:https://www.cnblogs.com/manupstairs/archive/2012/11/09/2763439.html

通过Attached Property给控件绑定Command(二)相关推荐

  1. 通过Attached Property给控件绑定Command(三)

    第三篇会是我们讨论的终章.希望文中关于依赖属性和数据绑定的使用,能够抛砖引玉,各位各抒己见给我一些启迪. 首先我们看一下最终的XAML,可能在看到XAML后各位已经猜出了具体的实现.这次我又增加了第四 ...

  2. QT给控件绑定数据:setProperty

    setProperty().property()函数 bool setProperty(const char *name, const QVariant &value); QVariant p ...

  3. WPF中一个控件绑定另一个控件的属性

    原文:WPF中一个控件绑定另一个控件的属性 如同一个Grid中的一个按钮根据另一个按钮的显示与否作出不同的响应: 绑定的时候通过ElementName来指定控件 <Grid Margin=&qu ...

  4. .Net平台Winform两个ComboBox控件绑定同一个数据源

    今天WINFROM编程遇到这么一个问题:是有关WINFORM中两个comboBox控件绑定同一个数据源的问题,在窗体的界面上有两个comboBox,我在Form1_Load中对他们做了数据绑定(具体代 ...

  5. Devexpress TreeList控件绑定显示父子节点对像

    今天一位同事咨询Devexpress TreeList控件绑定自动显示父子节点对像,但结果是不会显示带父子节点关系,而是将所有的节点作为父节点显示出来了,对像类的代码如下 public class I ...

  6. Windows Presentation Foundation(WPF)中的数据绑定(使用XmlDataProvider作控件绑定)

    原文:Windows Presentation Foundation(WPF)中的数据绑定(使用XmlDataProvider作控件绑定) ------------------------------ ...

  7. Winform开发之ComboBox和ComboBoxEdit控件绑定key/value数据

    使用 ComboBox 控件绑定key/value值: 因为 ComboBox 是有 DataSource 属性的,所以它可以直接绑定数据源,如 DataTable.ListItem 等. 使用 Da ...

  8. Asp.net--DropDownList控件绑定数据库数据

    DropDownList控件绑定数据库数据:DB是公共类,reDt是公共类中的方法 放在Page_Load事件中 if (!IsPostBack){DB db = new DB();DataTable ...

  9. java实现控件绑定数据源_控件(三)——TreeView控件以XmlDataSource控件为数据源实现简单的绑定...

    TreeView控件功能非常强大,今天,我们只是窥其一角. 我们实现的例子是:TreeView控件与XmlDataSource控件绑定,然后在网页显示选中项. 首先我们添加一个xml,取名为tv.xm ...

最新文章

  1. apache评分表的意义_APACHE评分系统及评分表
  2. css03层次选择器
  3. python数据结构题目_《数据结构与算法Python语言描述》习题第二章第三题(python版)...
  4. Codeforces Round #497 (Div. 1)
  5. java的传值调用什么_Java的传值调用
  6. MyEclipse配置Tomcat 6
  7. 【jQuery笔记Part2】05-jQuery自定义动画
  8. c/c++笔试面试题(1)
  9. java怎么把弹框设置为圆角_自定义圆角Dialog
  10. ultraedit查找每行第二个单词_算法4th3:查找
  11. android 手机头提示消息,正确的手机头部声明(android,iphone)
  12. c语言 大数开方,c语言求一个数的平方根
  13. rdpwrap 在 GitHub上 被禁了,谁能提供 autoupdate-v07.09.2019.zip ? 给分
  14. 重心法求中心matlab,两个中转站选址问题(重心法,metlab,spss)程序.ppt
  15. 面试java工程师,面试官一般问什么问题?
  16. 常见计算机网络协议汇总
  17. 图解快速排序(C++实现)
  18. java halt_Java Runtime halt()方法
  19. 从网络出发讲透Harmonious Attention Network for Person Re-Identification你不懂的细节
  20. 蓝牙遥控器连接流程分析

热门文章

  1. python中mode_python中的model模板中的数据类型
  2. list修改元素的值_Python 到底是值传递还是引用传递
  3. springboot怎么替代jsp_如何在SpringBoot中使用JSP ?但强烈不推荐,果断改Themeleaf吧...
  4. HALCON检测字符日期
  5. msvc 编译路径_Colmap编译教程
  6. mac mysql log_mac如何开启mysql bin-log
  7. stm32单片机屏幕一直闪_stm32实现LED灯的闪烁
  8. jsp弹窗修改信息_WEB最最最初级修改用户信息
  9. 《使用CSLA 2019:CSLA .NET概述》原版和机译文档下载
  10. Cocos Creator快速开通联网服务教程