CLR属性为C#自带的机制,而依赖属性目前多应用于WPF项目中依赖属性是通过对属性进行包装后的技术,主要目的
1. 了解决使用继承造成的复杂层次结构;

  1. 解决属性多次集成使用造成的内存暴涨
  2. 依赖属性可以通过Binding,依赖于其他对象上

    依赖属性

  3. 定义并注册依赖属性

  4. 约定依赖属性需要以属性名称开头,以xxxProperty结尾
  5. 注册依赖属性时,需要指定
  6. 属性名称
  7. 属性类型
  8. 拥有的类
  9. 默认值
  10. 验证回调函数,通常用于验证相关数据是否有效

    1. public class MyProdp : DependencyObject // 必须继承于该属性
    2. {
    3. // 定义包装属性类
    4. public string MyName
    5. {
    6. get { return (string)GetValue(MyNameProperty); }
    7. set { SetValue(MyNameProperty, value); }
    8. }
    9. // Using a DependencyProperty as the backing store for MyName. This enables animation, styling, binding, etc...
    10. public static readonly DependencyProperty MyNameProperty =
    11. DependencyProperty.Register(
    12. "MyName",// 属性名称
    13. typeof(string),// 属性类型
    14. typeof(MyProdp),// 属性拥有者
    15. new PropertyMetadata(string.Empty),//默认值
    16. (objec) =>// 验证回调函数
    17. {
    18. return true;
    19. }
    20. );
    21. }
  11. 依赖属性的获取的优先级,从低到高

  12. 默认值
  13. 上级元素继承而来的值
  14. DefaultStyle
  15. 由Style Trigger设置值
  16. 模版触发器 Template Trigger
  17. StyleTrigger
  18. Implicit Style
  19. 上级元素的 Template 设置的值
  20. 即本地值
  21. 由动画过程控制的只
  22. WPF属性系统强制值
  23. 依赖属性的使用
  24. 一般配合绑定进行操作
  25. 依赖属性的验证,事件回调

    依赖属性存储赋值原理

    参考书籍深入浅出WPF

  26. DependencyProperty.Register 创建一个DependencyPropert属性,

  27. 该类型中使用:_name.getHashCode^_ownerType.GetHashCode重FromNamKey的HashCode
  28. 并在静态属性HashTable PropertyFromName中,设置PropertyFromName[hashCode]=dp,这样就全局保存了该依赖属性。
  29. 对依赖属性的访问,可通过HashTable快速访问,但是DependencyPropert的hashCode返回的是GloableIndex,该Index确保每个DependencyProperty的实例是唯一的。
  30. DependencyObject 提供GetValue(XXXProperty),SetValue(XXXProperty)来操作依赖属性
  31. 在GetValue方法内部通过DependcuyProperty的GloableIndex再EffectiveValueEnty[] 数组内查找相关的值
  32. 在SetValue方法中,
  33. 首先判断值是否为UnsetValue,如果是则清空现有值
  34. 检查EffectiveValueEntry数组中是否已经有相关的值,有就改写,无就新增
  35. 调用UpdateEffective对新值进行处理。

    附加属性

    属性本身不属于该对象,只是后续因为需求而将该属性附加到该对象中;
    1. 定义附加属性 ```csharp public static int GetAttach(DependencyObject obj) { return (int)obj.GetValue(AttachProperty); }

public static void SetAttach(DependencyObject obj, int value) { obj.SetValue(AttachProperty, value); }

// Using a DependencyProperty as the backing store for Attach. This enables animation, styling, binding, etc… public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached(“Attach”, typeof(int), typeof(MyProdp), new PropertyMetadata(0));

  1. 1. 使用附加属性
  2. ```csharp
  3. Student student = new Student() { Name = "张鑫" };// Studetn为DependencyObject
  4. MyProdp.SetGradeDp(student, 1);// 将附加属性绑定到Student的容器中
  5. MessageBox.Show(string.Format("学生姓名:{0},年级:{1}", student.Name, MyProdp.GetGradeDp(student)));// 从student中查找相关的附加属性
  1. 用途及意义
  2. 可以在父级控件中定义子元素可能会用到的属性,而子级元素使用是无需考虑继承
  3. 子元素可以动态添加多种附加属性,增加了代码的灵活性
  4. 区别于依赖属性,附加属性只是把EffectiveValue的值存储到了子级元素中

    依赖属性值验证

    在注册依赖属性是,可以注册相关的验证回调,该回调不在元数据中 ```csharp public static readonly DependencyProperty AgeProperty = DependencyProperty.Register(“Age”, typeof(int), typeof(Student), new PropertyMetadata(0) {

}, validateValueCallback: (obj) => { // 注册验证回调 int studentAge = 0; if (int.TryParse(obj.ToString(), out studentAge)) { return studentAge >= 0 && studentAge < 150; }; return false; }); ```