依赖项属性在WPF界面中扮演着核心角色,是WPF很多重要功能的基础,从原理上讲,它劫持了windows窗口的消息循环,使得窗口能实时应对属性变化进行重绘,并且从一个属性影响到其他属性
一。注册依赖项
1.定义依赖项属性
(所有的依赖项都应设定成static readonly并在静态构造函数中赋值)
public static readonly DependencyProperty RedColorProperty;
2.属性包装器
public int RedColor
{
set { SetValue(RedColorProperty, value); }
get { return (int)GetValue(RedColorProperty); }
}
3.静态构造函数中设定FrameworkPropertyMetadata
FrameworkPropertyMetadata meta0 =
new FrameworkPropertyMetadata(
0/*默认值*/,
FrameworkPropertyMetadataOptions.AffectsRender/*参数flg*/,
RGBColorPropertyChanged, //changed回调
RGBColorCoerce);//修正回调
4.赋值注册依赖项
RedColorProperty=DependencyProperty.Register(
"RedColor"/*属性名*/,
typeof(int)/*属性类型*/,
typeof(MyButton)/*父类型*/,
meta0/*PropertyMetadata*/,
IsColorValid/*验证回调*/);
5.回调函数
//属性变化时回调
private static void RGBColorPropertyChanged(
DependencyObject d,DependencyPropertyChangedEventArgs e)
{
MyButton bt = d as MyButton;
if(bt!=null)
{
bt.Foreground = new SolidColorBrush(Color.FromRgb((byte)bt.RedColor, (byte)bt.GreenColor, (byte)bt.BlueColor));
}
}
//属性变化前验证前回调以修正属性值
private static object RGBColorCoerce(
DependencyObject d, object value)
{
int colorvalue = (int)value;
if (colorvalue > 255) return 255;
else if (colorvalue < 0) return 0;
else return colorvalue;
}
//属性变化前验证,判断是否合法,合法返回true
private static bool IsColorValid(object value)
{
int colorvalue = (int)value;
if (colorvalue > 255 || colorvalue < 0) return false;
return true;
}
完整示例
<local:MyButton Grid.Row="0" FontSize="72" RedColor="210" GreenColor="10" BlueColor="10">
<sys:DateTime>3/4/2016 3:02 PM</sys:DateTime>
</local:MyButton>
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows;//DependencyProperty定义必要
namespace San13DramaEditor
{
public class MyButton : Button
{
protected override void OnClick()
{
/*写入的代码*/
base.OnClick();
}
//定义依赖项属性
public static readonly DependencyProperty RedColorProperty;
public static readonly DependencyProperty GreenColorProperty;
public static readonly DependencyProperty BlueColorProperty;
//属性包装器
public int RedColor
{
set { SetValue(RedColorProperty, value); }
get { return (int)GetValue(RedColorProperty); }
}
public int GreenColor
{
set { SetValue(GreenColorProperty, value); }
get { return (int)GetValue(GreenColorProperty); }
}
public int BlueColor
{
set { SetValue(BlueColorProperty, value); }
get { return (int)GetValue(BlueColorProperty); }
}
//静态构造函数中注册依赖项属性
static MyButton()
{
FrameworkPropertyMetadata meta0 =
new FrameworkPropertyMetadata(
0/*默认值*/,
FrameworkPropertyMetadataOptions.AffectsRender/*参数flg*/,
RGBColorPropertyChanged, //changed回调
RGBColorCoerce);//修正回调
FrameworkPropertyMetadata meta1 =
new FrameworkPropertyMetadata(
0/*默认值*/,
FrameworkPropertyMetadataOptions.AffectsRender/*参数flg*/,
RGBColorPropertyChanged, //changed回调
RGBColorCoerce);//修正回调
FrameworkPropertyMetadata meta2 =
new FrameworkPropertyMetadata(
0/*默认值*/,
FrameworkPropertyMetadataOptions.AffectsRender/*参数flg*/,
RGBColorPropertyChanged, //changed回调
RGBColorCoerce);//修正回调
RedColorProperty=DependencyProperty.Register(
"RedColor"/*属性名*/,
typeof(int)/*属性类型*/,
typeof(MyButton)/*父类型*/,
meta0/*PropertyMetadata*/,
IsColorValid/*验证回调*/);
GreenColorProperty=DependencyProperty.Register(
"GreenColor"/*属性名*/,
typeof(int)/*属性类型*/,
typeof(MyButton)/*父类型*/,
meta1/*PropertyMetadata*/,
IsColorValid/*验证回调*/);
BlueColorProperty=DependencyProperty.Register(
"BlueColor"/*属性名*/,
typeof(int)/*属性类型*/,
typeof(MyButton)/*父类型*/,
meta2/*PropertyMetadata*/,
IsColorValid/*验证回调*/);
}
//静态构造函数中引用的回调方法
//属性变化时回调
private static void RGBColorPropertyChanged(
DependencyObject d,DependencyPropertyChangedEventArgs e)
{
MyButton bt = d as MyButton;
if(bt!=null)
{
bt.Foreground = new SolidColorBrush(Color.FromRgb((byte)bt.RedColor, (byte)bt.GreenColor, (byte)bt.BlueColor));
}
}
//属性变化前验证前回调以修正属性值
private static object RGBColorCoerce(
DependencyObject d, object value)
{
int colorvalue = (int)value;
if (colorvalue > 255) return 255;
else if (colorvalue < 0) return 0;
else return colorvalue;
}
//属性变化前验证,判断是否合法,合法返回true
private static bool IsColorValid(object value)
{
int colorvalue = (int)value;
if (colorvalue > 255 || colorvalue < 0) return false;
return true;
}
}
}
二。共享依赖项
静态构造函数中调用共享依赖项属性的AddOwner()方法
public class MyButton2 : Button
{
//定义依赖项属性
public static readonly DependencyProperty RedColorProperty;
//属性包装器
public int RedColor
{
set { SetValue(RedColorProperty, value); }
get { return (int)GetValue(RedColorProperty); }
}
//共享依赖项属性
static MyButton2()
{
RedColorProperty = MyButton.RedColorProperty.AddOwner(typeof(MyButton2));
}
}
三。附加依赖项
//定义依赖项属性
public static readonly DependencyProperty RedColorProperty;
//附加依赖项属性
static MyButton2()
{
FrameworkPropertyMetadata meta0 =
new FrameworkPropertyMetadata(
0/*默认值*/,
FrameworkPropertyMetadataOptions.AffectsRender/*参数flg*/,
RGBColorPropertyChanged, //changed回调
RGBColorCoerce);//修正回调
RedColorProperty = DependencyProperty.RegisterAttached(
"RedColor"/*属性名*/,
typeof(int)/*属性类型*/,
typeof(MyButton)/*父类型*/,
meta0/*PropertyMetadata*/,
IsColorValid/*验证回调*/);
}
MyButton mb = new MyButton();
mb.SetValue(MyButton2.RedColorProperty, 20);
四。总结:
1)注册依赖项时,
1.定义public static readonly DependencyProperty类型
2.定义一个属性,通过DependencyObject中的静态方法SetValue和GetValue包装依赖项
3.静态构造函数中用FrameworkPropertyMetadataOptions和可选的两个回调函数实例化FrameworkPropertyMetadata
4.静态构造函数中用FrameworkPropertyMetadata和可选的验证回调通过DependencyProperty.Register静态方法注册依赖项并赋值
5.完成三个可选的回调函数
2)共享依赖项时,定义依赖项和属性包装器后,在使用类的静态构造函数中调用共享类的依赖项属性的AddOwner()方法。也可以重新提供验证回调和metadata对象
3)附加依赖项时,定义依赖项后不定义属性包装器,在静态构造函数中使用DependencyProperty.RegisterAttached替代DependencyProperty.Register,在之后的使用中直接调用SetValue和GetValue方法绕过属性包装器。