依赖项属性

依赖项属性时WPF对.NET属性系统的扩展,用途在于提供一种方法来基于其他输入的值计算属性值,也就是说依赖项属性的值可能是通过以下途径获取:1.通过主题和用户首选项等系统属性;2.通过数据绑定或动画等来实时确定;3.通过资源和样式;4通过在元素树中的父子关系继承而来等。而且依赖项属性可通过独立验证、默认值、回调方法来修改属性值。
下面来看看定义一个依赖项属性的过程:
1. 定义依赖项属性
依赖项属性对象都是DependencyProperty类的实例,且考虑到依赖项属性可以被父子元素之间继承,即在不同类之间共享,所以依赖项属性都为静态字段。如下:
public static readonly DependencyProperty MarginProperty;
2 注册依赖项属性
通过以下代码注册依赖项属性:
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(
new Thickness(), FrameworkPropertyMetadataOption.AffectsMeasure);
MarginProperty = DependencyProperty.Register("Margin", 
typedef(Thickness), typeof(FrameworkElement), metadata,
new ValidateValueCallback(FrameworkElement.IsMarginValid));
注册依赖项属性要经过上面两步:
1.定义依赖项属性
创建FrameworkPropertyMetadata对象作为依赖项属性的默认值。上例中使用的构造函数中第一个参数为默认值,第二个参数为确定概述行的行为(如值更改发生的时间是否属性值继承等)。还有另一些重载的构造函数,有的含有指定属性值改变时的回调函数;
2. 注册依赖项属性
然后通过DependencyProperty.Register方法注册事件,第一个参数确定依赖项属性的名称,第二个参数确定依赖项属性值的类型,第三个参数确定依赖项属性的所有者,第四个参数确定默认值,最后一个参数确定验证属性的回调函数
3. 添加属性包装器
依赖项属性的存取器要使用DependencyObject中的GetValue和SetValue方法来存取,示例如下:
public Thickness Margin
{
set { SetValue(MarginProperty, value); }
get { return (Thickness)GetValue(MarginProperty); }
}
如上过程便可创建一个依赖项属性。
依赖项属性的一个重要功能是动态值识别,WPF确定一个属性的值会按下列顺序确定基本值:
1. 默认值
2. 继承而来的值
3. 来自主题样式的值
4. 来自项目样式的值
5. 本地值
而基本值未必是最后从属性中检索到的值,因为还存在其他改变属性值的提供者。所以WPF决定属性值得过程为:
1. 确定基本值
2. 如果属性值是个表达式,则对表达式进行求值
3. 如果属性是动画的目标,则应用动画
4. 调用回调函数修正属性值
下面使用一个完整的示例展示依赖项属性的使用。在WPF中没有通知栏控件,所以这儿使用WinForm中的NotifyIcon控件封装出一个WPF通知控件,具体代码如下:
  1 public class NotificationAreaIcon : FrameworkElement
  2 {
  3 //对Forms.NotifyIcon控件封装
  4 public static Forms.NotifyIcon notifyIcon;
  5 
  6 //添加鼠标点击路由事件
  7 public static readonly RoutedEvent MouseClickEvent = EventManager.RegisterRoutedEvent(
  8 "MouseClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(NotificationAreaIcon));
  9 
 10 //添加鼠标双击路由事件
 11 public static readonly RoutedEvent MouseDoubleClickEvent = EventManager.RegisterRoutedEvent(
 12 "MouseDoubleClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(NotificationAreaIcon));
 13 
 14 //注册依赖项属性Icon
 15 public static readonly DependencyProperty IconProperty =
 16 DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NotificationAreaIcon));
 17 
 18 //注册依赖项属性Text
 19 public static readonly DependencyProperty TextProperty =
 20 DependencyProperty.Register("Text", typeof(string), typeof(NotificationAreaIcon));
 21 
 22 //注册依赖项属性MenuItems
 23 public static readonly DependencyProperty FormsContextMenuProperty =
 24 DependencyProperty.Register("MenuItems", typeof(List<Forms.MenuItem>), typeof(NotificationAreaIcon), new PropertyMetadata(new List<Forms.MenuItem>()));
 25 
 26 //初始化事件
 27 protected override void OnInitialized(EventArgs e)
 28 {
 29 base.OnInitialized(e);
 30 
 31 // Create and initialize the window forms notify icon based
 32 notifyIcon = new Forms.NotifyIcon();
 33 notifyIcon.Text = Text;
 34 if (!DesignerProperties.GetIsInDesignMode(this))
 35 {
 36 notifyIcon.Icon = FromImageSource(Icon);
 37 }
 38 notifyIcon.Visible = FromVisibility(Visibility);
 39 
 40 if (this.MenuItems != null && this.MenuItems.Count > 0)
 41 {
 42 notifyIcon.ContextMenu = 
 43 new System.Windows.Forms.ContextMenu(this.MenuItems.ToArray());
 44 }
 45 
 46 notifyIcon.MouseDown += OnMouseDown;
 47 notifyIcon.MouseUp += OnMouseUp;
 48 notifyIcon.MouseClick += OnMouseClick;
 49 notifyIcon.MouseDoubleClick += OnMouseDoubleClick;
 50 
 51 Dispatcher.ShutdownStarted += OnDispatcherShutdownStarted;
 52 }
 53 
 54 private void OnDispatcherShutdownStarted(object sender, EventArgs e)
 55 {
 56 notifyIcon.Dispose();
 57 }
 58 
 59 public void DestroyIcon()
 60 {
 61 notifyIcon.Dispose();
 62 }
 63 
 64 private void OnMouseDown(object sender, Forms.MouseEventArgs e)
 65 {
 66 OnRaiseEvent(MouseDownEvent, new MouseButtonEventArgs(
 67 InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
 68 }
 69 
 70 private void OnMouseUp(object sender, Forms.MouseEventArgs e)
 71 {
 72 OnRaiseEvent(MouseUpEvent, new MouseButtonEventArgs(
 73 InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
 74 }
 75 
 76 private void OnMouseDoubleClick(object sender, Forms.MouseEventArgs e)
 77 {
 78 OnRaiseEvent(MouseDoubleClickEvent, new MouseButtonEventArgs(
 79 InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
 80 }
 81 
 82 private void OnMouseClick(object sender, Forms.MouseEventArgs e)
 83 {
 84 OnRaiseEvent(MouseClickEvent, new MouseButtonEventArgs(
 85 InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
 86 }
 87 
 88 private void OnRaiseEvent(RoutedEvent handler, MouseButtonEventArgs e)
 89 {
 90 e.RoutedEvent = handler;
 91 RaiseEvent(e);
 92 }
 93 
 94 public List<Forms.MenuItem> MenuItems
 95 {
 96 get { return (List<Forms.MenuItem>)GetValue(FormsContextMenuProperty); }
 97 set { SetValue(FormsContextMenuProperty, value); }
 98 }
 99 
100 public ImageSource Icon
101 {
102 get { return (ImageSource)GetValue(IconProperty); }
103 set { SetValue(IconProperty, value); }
104 }
105 
106 public string Text
107 {
108 get { return (string)GetValue(TextProperty); }
109 set { SetValue(TextProperty, value); }
110 }
111 
112 public event MouseButtonEventHandler MouseClick
113 {
114 add { AddHandler(MouseClickEvent, value); }
115 remove { RemoveHandler(MouseClickEvent, value); }
116 }
117 
118 public event MouseButtonEventHandler MouseDoubleClick
119 {
120 add { AddHandler(MouseDoubleClickEvent, value); }
121 remove { RemoveHandler(MouseDoubleClickEvent, value); }
122 }
123 
124 #region Conversion members
125 
126 private static Drawing.Icon FromImageSource(ImageSource icon)
127 {
128 if (icon == null)
129 {
130 return null;
131 }
132 Uri iconUri = new Uri(icon.ToString());
133 return new Drawing.Icon(Application.GetResourceStream(iconUri).Stream);
134 }
135 
136 private static bool FromVisibility(Visibility visibility)
137 {
138 return visibility == Visibility.Visible;
139 }
140 
141 private MouseButton ToMouseButton(Forms.MouseButtons button)
142 {
143 switch (button)
144 {
145 case Forms.MouseButtons.Left:
146 return MouseButton.Left;
147 case Forms.MouseButtons.Right:
148 return MouseButton.Right;
149 case Forms.MouseButtons.Middle:
150 return MouseButton.Middle;
151 case Forms.MouseButtons.XButton1:
152 return MouseButton.XButton1;
153 case Forms.MouseButtons.XButton2:
154 return MouseButton.XButton2;
155 }
156 throw new InvalidOperationException();
157 }
158 
159 #endregion Conversion members
160 }





原文地址:https://www.cnblogs.com/lvniao/p/3564611.html