附加属性,你们都不陌生,最多见的是Canvas.Left/Canvas.Top,相似的也有Grid.Row/Grid.Column等附加属性。举个最多见的例子html
<Canvas> <Ellipse Fill="Red" Width="100" Height="60" Canvas.Left="56" Canvas.Top="98"/> </Canvas>
须要说明的是并非全部的附加属性都是元素放进去后才会有附加效果,上面的例子只是恰好是这种错觉的巧合状况,Grid.Row也属于这种巧合。
仍是举个反例来讲明编辑器
<Canvas> <Button Content="Copy" ToolTip="Copy the Selected Items"ToolTipService.ShowOnDisabled="True"/> </Canvas>
ToolTipService类是一个静态类,和Button风马牛不相及,二者之间没有任何关系。ide
这就是关于附加属性DebugLZQ认为须要说明的地方。post
1.咱们有这样的一个XAMLurl
<Canvas> <Ellipse Fill="Red" Width="100" Height="60" /> <Rectangle Fill="Blue" Width="80" Height="80" Canvas.Left="100" Canvas.Top="100" /> <Button Content="Hello" Canvas.Left="130" Canvas.Top="30" FontSize="20" /> </Canvas>
假如,咱们须要实现控件绕中心旋转必定的角度。一般咱们须要写相似的Rotatespa
<Ellipse Fill="Red" Width="100" Height="60" RenderTransformOrigin=".5,.5"> <Ellipse.RenderTransform> <RotateTransform Angle="30" /> </Ellipse.RenderTransform> </Ellipse>
固然这样OK,程序运行没有问题。
但,缺点是须要写较多的代码;当咱们须要为页面其余全部元素实现旋转时,又须要写大量相似的代码。code
咱们能够经过附加属性来简化代码。如何作呢?orm
2.为工程添加一个名为RotationManager的类,咱们在这个类中添加一个附加属性,让其余都能使用这个附加属性。xml
咱们在类中键入"propa"htm
和依赖属性相似,连按2次Tab,修改相应命名,以下:
public static double GetAngle(DependencyObject obj) { return (double)obj.GetValue(AngleProperty); } public static void SetAngle(DependencyObject obj, double value) { obj.SetValue(AngleProperty, value); } public static readonly DependencyProperty AngleProperty = DependencyProperty.RegisterAttached("Angle", typeof(double), typeof(RotationManager), new PropertyMetadata(0.0));
这样咱们就完成了附加属性的定义。
为了可以在XAML中使用,在XAML中添加以下映射。
<Window x:Class="CreatingAnAttachedProperty.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CreatingAnAttachedProperty"
这样,页面上的元素就可使用这个附加属性了,以下:
<Canvas> <Ellipse Fill="Red" Width="100" Height="60" Canvas.Left="56" Canvas.Top="98" local:RotationManager.Angle="30"/> <Rectangle Fill="Blue" Width="80" Height="80" Canvas.Left="285" Canvas.Top="171" local:RotationManager.Angle="45" /> <Button Content="Hello" Canvas.Left="265" Canvas.Top="48" FontSize="20" local:RotationManager.Angle="60"/> </Canvas>
3.此时编辑器,没有任何旋转,若咱们此时运行程序,也没有任何的旋转效果,为何?由于咱们只是添加了一个附加属性,给它付了个初值,当值改变的时候,咱们并无添加相应的处理逻辑。
依次,咱们须要返回RotationManager.cs添加相应的值改变事件及事件处理逻辑。以下:
public static readonly DependencyProperty AngleProperty = DependencyProperty.RegisterAttached("Angle", typeof(double), typeof(RotationManager), new PropertyMetadata(0.0,OnAngleChanged)); private static void OnAngleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { var element = obj as UIElement; if (element != null) { element.RenderTransformOrigin = new Point(0.5, 0.5); element.RenderTransform = new RotateTransform((double)e.NewValue); } }
添加完成后,咱们在编辑器中,看到以下效果:
若是咱们运行,则效果以下:
相比于前面挨个挨个的添加Rotate效果,程序是Clearn不少?这就是附加属性带来的便利。
完整的RotationManager.cs以下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media;//necessary namespace CreatingAnAttachedProperty { class RotationManager:DependencyObject { public static double GetAngle(DependencyObject obj) { return (double)obj.GetValue(AngleProperty); } public static void SetAngle(DependencyObject obj, double value) { obj.SetValue(AngleProperty, value); } public static readonly DependencyProperty AngleProperty = DependencyProperty.RegisterAttached("Angle", typeof(double), typeof(RotationManager), new PropertyMetadata(0.0,OnAngleChanged)); private static void OnAngleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { var element = obj as UIElement; if (element != null) { element.RenderTransformOrigin = new Point(0.5, 0.5); element.RenderTransform = new RotateTransform((double)e.NewValue); } } } }
Update:
WPF: Creating parameterized styles with attached properties
Wish it helps.