可绑定属性在宿主类上定义,并在XAML文件中的宿主类元素上使用,我们使用的大多数属性都是如此,如【<Grid BackgroundColor="AliceBlue"></Grid>】,附加属性BackgroundColor在宿主类Grid上定义,并在宿主元素<Grid>上使用。附加属性也是可绑定属性,在宿主类的定义(定义方式有一些差异),但是,附加属性在XAML文件中的“非宿主类”上赋值使用。
一、创建和使用附加属性的简单案例
1、可绑定对象和附加属定的定义
public class Shadow:ContentView { //和可绑定属性不同,这里调用的是CreateAttached方法 //在HashTable上建立一个Hashcode和BindableProperty对象的键值对 public static readonly BindableProperty HasShadowProperty = BindableProperty.CreateAttached("HasShadow",typeof(bool),typeof(Shadow),false); //和可绑定属性不同,这里使用GetHasShadow和SetHasShadow两个方法对属性进行包装(访问属性) //参数view为XAML文件中,使用附加属性的非宿主元素对象 //调用view的GetValue和SetValue方法进行存取值 //实际上还是在BindableProperty对象的小房间(可扩充数组)里存取值,但区别在于增加的非宿主元素的检索要素 public static bool GetHasShadow(BindableObject view) { return (bool)view.GetValue(HasShadowProperty); } public static void SetHasShadow(BindableObject view,bool value) { view.SetValue(HasShadowProperty, value); } }
2、第二步:在XAML中使用使用附加属性(注:本案例未设置控件的外观,所以在UI层并不能看到控件)
//方法一:XAML中使用附加属性 <VerticalStackLayout> <Label Text="使用HasShadow" control:Shadow.HasShadow="True"/> </VerticalStackLayout> //方法二:后台代码中使用附加属性 Label label = new Label { Text = "使用HasShadow" }; Shadow.SetHasShadow (label, true);
二、进一步解释原理
- 首先要说明的是,虽然上例中,我们使用了Shadow、HasShadow等具有意义的名称,但仅仅通过上面的代码,Shadow和HasShadow并没有实际意义,即使HasShadow等于true,元素也不会神奇的就有了阴影。上面的代码,仅仅是定义了一个名称为HasShadow的属性,然后可以给它赋值为true或false。只有我们使用控件模板好,使用这个属性值来定义UI,它才具有了实际意义。
- 如果我们从HashTable和小房间的底层原理来理解附加属性,其实它和可绑定属性的差异非常小,仅仅是在小房间中存取值时,检索的房间号里,多了非宿主元素的代码。比如来的房间号是301,现在变成了label.301,button.301,这样就能识别是哪个非宿主对象在使用它,从而可以对这些非宿主对象施加UI的影响。
- 可绑定属性和附加属性,本质上就是改变了存取值的方式。原来每创建一个对象,就要为所有属性的back字段分配内存空间,现在不用了,只有需要用到的属性,才分配内存空间,大大节省了内存空间。同时,原来的数据都保存在一个个对象里,现在数据虽然还是分开保存在小房间里,但是检索方式和存取方式都发生了根本变化,性能效率更加高。
- 虽然附加属性的本质和可绑定属性是一样的,但可以让我们更加方便的使用XAML,可以想象,如果Grid子元素的所有Row和Column值,都在Grid上分配,一不直观,二也更加繁琐。