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


      第三篇会是我们讨论的终章。希望文中关于依赖属性和数据绑定的使用,能够抛砖引玉,各位各抒己见给我一些启迪。

      首先我们看一下最终的XAML,可能在看到XAML后各位已经猜出了具体的实现。这次我又增加了第四个Rectangle,颜色是Gray。同时对该Rectangle设置了Name=“rect”。

    <Rectangle x:Name="rect" Width="100" Height="100" Fill="Gray"></Rectangle>
    <local:ElementBinder EventName="MouseLeftButtonDown" 
                         Command="{Binding ViewModel.MouseLeftDownCommand, ElementName=window}"
                         Parameter="{Binding ElementName=rect}"
                         Target="{Binding ElementName=rect}">
    </local:ElementBinder>

      我们注意到其实ElementBinder并不是Rectangle的属性,而仅仅是ElementBinder中的Target属性绑定了Rectangle。

      这其中的不同在于ElementBinder是继承自FrameworkElement,而其中的EventName、Command、Parameter和Target都从附加属性变成了普通的依赖属性。不再附加到其他的某个DependencyObject之上,而仅仅是作为ElementBinder的属性存在。之所以继承自FrameworkElement,是因为在该类提供了数据绑定的能力,如果继承自UIElement就无法实现Binding的功能了。

      其实ElementBinder这个类写在XAML里,并没有和任何的控件产生关联,之所以可以绑定Command到Rectangle,是因为新增的Target属性。通过该属性才取得了与某个UIElement(这里是Rectangle)的联系。

            public UIElement Target
            {
                get { return (UIElement)GetValue(TargetProperty); }
                set { SetValue(TargetProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Target.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TargetProperty =
                DependencyProperty.Register("Target", typeof(UIElement), typeof(ElementBinder), new UIPropertyMetadata(ChangedCallback));
    
            private static void ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                UIElement element = d.GetValue(TargetProperty) as UIElement;
                if (element != null)
                {
                    string eventName = d.GetValue(EventNameProperty) as string;
                    if (eventName != null)
                    {
                        EventInfo eventInfo = element.GetType().GetEvent(eventName);
                        var handler = new MouseButtonEventHandler((sender, arg) =>
                        {
                            object obj = d.GetValue(ParameterProperty);
                            ICommand command = d.GetValue(CommandProperty) as ICommand;
                            command.Execute(obj);
                        });
                        var del = handler.GetInvocationList()[0];
    
                        eventInfo.AddEventHandler(element, del);
                    }
                }
            }

      在代码中我们首先找到了ElementBinder对象的Target属性,取得Target属性的值,也正是我们希望关联的控件Rectangle,之后的逻辑和前面一篇是一样的。

      本来是没有打算写第三篇的,这个通过FrameworkElement建立关联来绑定的思路也不是我想到的,是得到上篇提到的微软哥韦恩卑鄙给出的解决方案。在学习了之后我也分享给大家。

      链接包含了文中所用到的代码,我总共创建了4个Rectangle,又用了4种不同的方式去关联Command,如果各位闲暇之余想出了“回字的第5种写法”,望不吝赐教。

      https://files.cnblogs.com/manupstairs/TestDPWpf.7z

  • 相关阅读:
    vue使用百度编辑器ueditor踩坑记录
    vue项目之webpack打包静态资源路径不准确
    用自己电脑做网站服务器
    telnet测试端口号
    mongodb,redis,mysql的区别和具体应用场景
    移动应用调试之Inspect远程调试
    @vue/cli 3配置文件vue.config.js
    vue+webpack多个项目共用组件动态打包单个项目
    koa/koa2项目搭建
    用Navicat复制数据库到本地(导入.sql文件运行)
  • 原文地址:https://www.cnblogs.com/manupstairs/p/2764232.html
Copyright © 2020-2023  润新知