第三篇会是我们讨论的终章。希望文中关于依赖属性和数据绑定的使用,能够抛砖引玉,各位各抒己见给我一些启迪。
首先我们看一下最终的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种写法”,望不吝赐教。