简介
Dependency Property: 它们依赖一些其他的property和外在的影响,引起自身的变化.
如: WPF框架的编程经常和界面打交道,经常遇到的一个情况是某个属性的值的变化会影响到多个其他对象。比如当一个Button的改变大小超过了它的容器,他的容器应该自动调整大小。于是我们考虑在每个属性的set方法中触发一些事件,但很快我们发现现有的功能很难满足我们的需求,至少不能简洁漂亮的满足这些需求。
定义示例: public static readonly DependencyProperty FontSizePropery;
1.简单的element tree
通过简单的例子来理解"沿袭"(不能说是继承)
窗口构造函数将Font size 初使化为16设备无关的单位. 所有的BUTTON都会沿袭这个设置(都是WINDOW的孩子)
![]()
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Windows;
5
using System.Windows.Controls;
6
using System.Windows.Documents;
7![]()
8
namespace DockAndGrid
9![]()
![]()
{
10
public class SetFontSizeProperty : Window
11![]()
{
12
[STAThread]
13
public static void Main()
14![]()
{
15
Application app = new Application();
16
app.Run(new SetFontSizeProperty());
17
}
18![]()
19
public SetFontSizeProperty()
20![]()
{
21
Title = "Set size property";
22
SizeToContent = SizeToContent.WidthAndHeight;
23
ResizeMode = ResizeMode.CanMinimize;
24
FontSize = 16;
25![]()
Double[] fntsizes =
{ 8,16,32};
26![]()
27
Grid grid = new Grid();
28
Content = grid;
29![]()
30
for (int i = 0; i < 2; i++)
31![]()
{
32
RowDefinition row = new RowDefinition();
33
row.Height = GridLength.Auto;
34
grid.RowDefinitions.Add(row);
35
}
36
for (int i = 0; i < fntsizes.Length; i++)
37![]()
{
38
ColumnDefinition col = new ColumnDefinition();
39
col.Width = GridLength.Auto;
40
grid.ColumnDefinitions.Add(col);
41
}
42![]()
43
for (int i = 0; i < fntsizes.Length; i++)
44![]()
{
45
Button btn = new Button();
46
btn.Content = new TextBlock(new Run("Set Window FontSize to " + fntsizes[i]));
47
btn.Tag = fntsizes[i];
48
btn.HorizontalAlignment = HorizontalAlignment.Center;
49
btn.VerticalAlignment = VerticalAlignment.Center;
50
btn.Click += this.WindowFontSizeOnClick;
51
grid.Children.Add(btn);
52
Grid.SetRow(btn, 0);
53
Grid.SetColumn(btn, i);
54![]()
55
btn = new Button();
56
btn.Content = new TextBlock(new Run("Set Button FontSize to " + fntsizes[i]));
57
btn.Tag = fntsizes[i];
58
btn.HorizontalAlignment = HorizontalAlignment.Center;
59
btn.VerticalAlignment = VerticalAlignment.Center;
60
btn.Click += this.ButtonFontSizeOnClick;
61
grid.Children.Add(btn);
62
Grid.SetRow(btn, 1);
63
Grid.SetColumn(btn, i);
64
}
65
}
66![]()
67
void WindowFontSizeOnClick(object sender, RoutedEventArgs args)
68![]()
{
69
Button btn = args.Source as Button;
70
FontSize = (double)btn.Tag;
71
}
72![]()
73
void ButtonFontSizeOnClick(object sender, RoutedEventArgs args)
74![]()
{
75
Button btn = args.Source as Button;
76
btn.FontSize = (double)btn.Tag;
77
}
78![]()
79
}
80
}
81![]()
element tree是我们能看到的(实际)能看到的视觉对像, 是对logic tree的简单处理,更容易理解程序 (font size如何被处理的), 在此程序中为window->grid->(button collection)->(textblock collection)
特点:树中较低的对像"沿袭"父亲的property,然而如果某个对像有明确的设定自己的font size,那么就不用沿袭父亲的这个property
注: Grid根本就没有fontsize property,但依然可以沿袭(内部机制,不是很明白)
property set priority: 对像自己的设定> 沿袭来的值 > 默认值
2. dependecy property 示例
在WPF中,dependency property的使用,允许以一般的方式自动进行大部分的通知.
定义: public static readonly DependencyProperty SpaceProperty;
它是public and static, 此成员只与类相关,而非与对象相关联.
注册: SpaceProperty = DependencyProperty.Register.("Name", typeof(datatype), typeof(ownertype));
实际上这个property不可以简单的这么完成,还要须要元数据等元素,并且由于是静态的成员,必须在静态构造函数中初使化
static SpaceButton()
{
//define metadata
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.DefaultValue = 1;
metadata.AffectsMeasure = true;
metadata.Inherits = true;
metadata.PropertyChangedCallback += OnSpacePropertyChanged;
//Register dependency property
SpaceProperty = DependencyProperty.Register("Space", typeof(int), typeof(SpaceButton),
metadata, ValidateSpaceValue);
}
ValidateSpaceValue: 检验值是否合法
AffectsMeasure: 影响控件的尺寸调整.
使用: .Net CLR wrapper
public int Space
{
set { SetValue(SpaceProperty, value); }
get { return (int)GetValue(SpaceProperty); }
}
注意:即使传到SetValue and GetValue方法内当参数的property的对象是静态的,而这两个方法却是实例方法, 它们的值的设定和取得都和特定的实例有关, 这个property维持目前的值,且处理所有的日常事务.
完整示例:
![]()
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Windows;
6
using System.Windows.Controls;
7
using System.Windows.Media;
8
using System.Windows.Input;
9![]()
10
namespace DependencyProperty1
11![]()
![]()
{
12
class SpaceButton : Button
13![]()
{
14
string txt;
15
public string Text
16![]()
{
17![]()
get
{ return txt; }
18
set
19![]()
{
20
txt = value;
21
Content = SpaceOutText(txt);
22
}
23
}
24![]()
25
public static readonly DependencyProperty SpaceProperty;
26
public int Space
27![]()
{
28![]()
set
{ SetValue(SpaceProperty, value); }
29![]()
get
{ return (int)GetValue(SpaceProperty); }
30
}
31![]()
32
static SpaceButton()
33![]()
{
34
//define metadata
35
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
36
metadata.DefaultValue = 1;
37
metadata.AffectsMeasure = true;
38
metadata.Inherits = true;
39
metadata.PropertyChangedCallback += OnSpacePropertyChanged;
40![]()
41
//Register dependency property
42
SpaceProperty = DependencyProperty.Register("Space", typeof(int), typeof(SpaceButton),
43
metadata, ValidateSpaceValue);
44
}
45![]()
46
static bool ValidateSpaceValue(object obj)
47![]()
{
48
int i = (int)obj;
49
return i >= 0;
50
}
51![]()
52
//Recall method, when the property change
53
static void OnSpacePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
54![]()
{
55
SpaceButton btn = obj as SpaceButton;
56
btn.Content = btn.SpaceOutText(btn.txt);
57
}
58![]()
59
private string SpaceOutText(string str)
60![]()
{
61
if (str == null)
62
return null;
63![]()
64
StringBuilder sb = new StringBuilder();
65
foreach (char ch in str)
66![]()
{
67
sb.Append(ch + new string(' ', Space));
68
}
69
return sb.ToString();
70
}
71
}
72![]()
73
public class SpaceWindow : Window
74![]()
{
75
public static readonly DependencyProperty SpaceProperty;
76
public int Space
77![]()
{
78![]()
set
{ SetValue(SpaceProperty, value); }
79![]()
get
{ return (int)GetValue(SpaceProperty); }
80
}
81![]()
82
static SpaceWindow()
83![]()
{
84
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
85
metadata.Inherits = true;
86![]()
87
//Add owner to SpacePropery and override metadata
88
SpaceProperty = SpaceButton.SpaceProperty.AddOwner(typeof(SpaceWindow));
89
SpaceProperty.OverrideMetadata(typeof(SpaceWindow), metadata);
90
}
91![]()
92
}
93![]()
94
public class SetSpaceProperty : SpaceWindow
95![]()
{
96
[STAThread]
97
public static void Main()
98![]()
{
99
Application app = new Application();
100
app.Run(new SetSpaceProperty());
101
}
102![]()
103
public SetSpaceProperty()
104![]()
{
105
Title = "Set Space property";
106![]()
107
SizeToContent = SizeToContent.WidthAndHeight;
108
ResizeMode = ResizeMode.CanMinimize;
109![]()
int[] iSpace =
{ 0,1,2};
110![]()
111
Grid grid = new Grid();
112
Content = grid;
113![]()
114
for (int i = 0; i < 2; i++)
115![]()
{
116
RowDefinition row = new RowDefinition();
117
row.Height = GridLength.Auto;
118
grid.RowDefinitions.Add(row);
119
}
120![]()
121
for (int i = 0; i < iSpace.Length; i++)
122![]()
{
123
ColumnDefinition col = new ColumnDefinition();
124
col.Width = GridLength.Auto;
125
grid.ColumnDefinitions.Add(col);
126
}
127![]()
128
for (int i = 0; i < iSpace.Length; i++)
129![]()
{
130
SpaceButton btn = new SpaceButton();
131
btn.Text = "Set window space to " + iSpace[i];
132
btn.Tag = iSpace[i];
133
btn.HorizontalAlignment = HorizontalAlignment.Center;
134
btn.VerticalAlignment = VerticalAlignment.Center;
135
btn.Click += this.WindowPropertyOnClick;
136
grid.Children.Add(btn);
137
Grid.SetRow(btn, 0);
138
Grid.SetColumn(btn, i);
139![]()
140
btn = new SpaceButton();
141
btn.Text = "Set button spae to " + iSpace[i];
142
btn.Tag = iSpace[i];
143
btn.HorizontalAlignment = HorizontalAlignment.Center;
144
btn.VerticalAlignment = VerticalAlignment.Center;
145
btn.Click += this.ButtonPropertyOnClick;
146
grid.Children.Add(btn);
147
Grid.SetRow(btn, 1);
148
Grid.SetColumn(btn, i);
149![]()
150
}
151
}
152![]()
153
void WindowPropertyOnClick(object sender, RoutedEventArgs args)
154![]()
{
155
SpaceButton btn = args.Source as SpaceButton;
156
Space = (int)btn.Tag;
157
}
158![]()
159
void ButtonPropertyOnClick(object sender, RoutedEventArgs args)
160![]()
{
161
SpaceButton btn = args.Source as SpaceButton;
162
btn.Space = (int)btn.Tag;
163
}
164![]()
165![]()
166
}
167
}
168![]()
[Question]Logical tree, Visual tree, will trace it in the next