8章 依赖属性
依赖属性,Dependency Property。
在使用上只需注意两点:
在一棵XAML视觉树上
1.当一个对象被明确设定依赖属性时,它的子孙都得到同样的属性
2.如果某个对象被明确设定属性,它就不再沿袭父亲的这个属性。此后,再改变父亲的属性,这个对象也不再受影响。
对Control类的FontSize属性的思考:
public class Control : FrameworkElement
{
double fontSize = 11;
public double FontSize
{
get
{
return fontSize;
}
set
{
fontSize = value;
……
}
}
}
在set写属性时,省略一些代码,用来激发其他事件。这里需要一种机制,以真正省略这些代码——这就是依赖属性的用意。
为此建立public而且static的只读字段FontSizeProperty,从而这个字段是和类相关而不是关联到对象,而且它只能在静态构造函数中被设定。
public partial class Control : FrameworkElement
{
public static readonly DependencyProperty FontSizeProperty;
static Control()
{
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.DefaultValue = 11;
metadata.AffectsMeasure = true;
metadata.Inherits = true;
metadata.IsDataBindingAllowed = true;
metadata.DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Control), metadata, ValidateFontSize);
}
static bool ValidateFontSize(Object obj)
{
double dFontSize = (double)obj;
return dFontSize > 0 && dFontSize < 35791;
}
}
注意这个对象的建立,使用了DependencyProperty.Register静态方法。
重载方法1:
FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Control));
三个参数分别为“和此依赖属性关联的名称字符串”、“属性的数据类型”、“注册此属性的类别”。
重载方法2:
FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Control), metadata, ValidateFontSize);
多了两个参数,讨论如下
有时候还需要metadata,来描述这个属性的重要信息。其中DefaultValue用来取代私有字段fontSize;AffectsMeasure一般设置为true,会使得FontSize的set属性设置时,以新的FontSize进行重绘;Inherits则影响这个控件以下的所有子孙,在FontSize的set属性设置时,将这个新的FontSize值向下传。
而ValidateFontSize这个callback方法,则用于FontSize的set属性设置时调用,以决定这个值是否合适。不合适也就是返回方法返回false,就抛出一个异常。
此时,改写FontSize属性,使其不再依赖私有字段fontSize,而是依赖于FontSizeProperty字段,并通过GetVale和SetValue这两个派生于DependencyObject的方法来操作,里面省略了一些内部处理的代码,包括很多事件的触发,如设置属性时对窗体重绘和子孙的影响。
public partial class Control : FrameworkElement
{
public double FontSize
{
get
{
return (double)GetValue(FontSizeProperty);
}
set
{
SetValue(FontSizeProperty, value);
}
}
}
自定义一个依赖属性
仿照对Control类的研究,设计一个带有依赖属性SpaceProperty的SpaceButton类
public class SpaceButton : Button
{
// A DependencyProperty and public property.
public static readonly DependencyProperty SpaceProperty;
public int Space
{
set
{
SetValue(SpaceProperty, value);
}
get
{
return (int)GetValue(SpaceProperty);
}
}
// Static constructor.
static SpaceButton()
{
// Define the metadata.
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.DefaultValue = 1;
metadata.AffectsMeasure = true;
metadata.Inherits = true;
metadata.PropertyChangedCallback += OnSpacePropertyChanged;
// Register the DependencyProperty.
SpaceProperty =
DependencyProperty.Register("Space", typeof(int),
typeof(SpaceButton), metadata,
ValidateSpaceValue);
}
// Callback method for value validation.
static bool ValidateSpaceValue(object obj)
{
int i = (int)obj;
return i >= 0;
}
// Callback method for property changed.
static void OnSpacePropertyChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
SpaceButton btn = obj as SpaceButton;
btn.Content = btn.SpaceOutText(btn.txt);
}
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15123181/viewspace-422967/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/15123181/viewspace-422967/