数据绑定是一种XAML界面和后台数据通信的方式,因为界面和后台数据的通信的场景有多种,并且数据于数据之间也存在着不一样的关联关系,所以数据绑定的实现技巧和方式也是多种多样的。下面我们全面地介绍数据绑定的实现原理和相关的语法基础。
11.1.1 数据绑定的原理
数据绑定主要包含两大模块,一是绑定目标,也就是UI界面这块,另一模块是绑定源,也就是给数据绑定提供数据的后台代码。然后这两大模块通过某种方式和语法关联起来,会互相影响或者只是一边对另一边产生影响,这就是数据绑定的基本原理。如图11.1所示,详细地描述了这一绑定的过程,不论要绑定什么元素,不论数据源的特性是什么,每个绑定都始终遵循这个图的模型。
图11.1 数据绑定示意图
如图数据绑定示意图所示,数据绑定实质上是绑定目标与绑定源之间的桥梁。 该图演示以下基本的Windows Phone数据绑定概念:
通常,每个绑定都具有四个组件:绑定目标对象、目标属性、绑定源,以及要使用的绑定源中的值的路径。例如,如果要将TextBox的内容绑定到Employee对象的Name属性,则目标对象是TextBox,目标属性是Text属性,要使用的值是Name,源对象是 Employee 对象。
绑定源又称为数据源,充当着一个数据中心的角色,是数据绑定的数据提供者,可以理解为最底下数据层。数据源是数据的来源和源头,它可以是一个UI元素对象或者某个类的实例,也可以是一个集合。
数据源作为一个实体可能保存着很多数据,具体关注它的哪个数值呢?这个数值就是路径(Path)。例如,要用一个Slider控件作为一个数据源,那么这个Slider控件会有很多属性,这些属性都是作为数据源来提供的,它拥有很多数据,除了Value之外,还有Width、Height等,这时候数据绑定就要选择一个最关心的属性来作为绑定的路径。例如,使用的数据绑定是为了监测Slider控件的值的变化,那么就需要把Path设为Value了。使用集合作为数据源的道理也是一样,Path的值就是集合里面的某个字段。
数据将传送到哪里去?这就是数据的目标,也就是数据源对应的绑定对象。绑定目标对象一定是数据的接收者、被驱动者,但它不一定是数据的显示者。目标属性则是绑定目标对象的属性,这个很好理解。目标属性必须为依赖项属性。大多数UIElement对象的属性都是依赖项属性,而大多数依赖项属性(除了只读属性)默认情况下都支持数据绑定。注意只DependencyObject类型可以定义依赖项属性,所有UIElement都派生自DependencyObject。
11.1.2 创建绑定
在Windows Phone的应用程序中创建一个数据绑定主要会有下面的三个步骤:
(1)定义源对象:源对象会给界面UI提供数据,在这一步就要创建与程序相关的数据类,通过这个类的对象来作为数据绑定的源。
(2)通过设置DataContext属性绑定到源对象, DataContext属性表示Windows Phone的UI元素的数据上下文,可以给UI元素提供数据,如果对当前的页面最顶层的Page设置其DataContext属性绑定到源对象,那么整个页面都可是使用该数据源提供的数据。
(3)使用Binding标记扩展来绑定数据源对象的属性,把UI的属性和数据源的属性关联起来。Binding是标记扩展,可以用Binding来声明包含一系列子句,这些子句跟在Binding关键字后面,并由逗号分隔。
下面给出创建绑定的示例:通过一个最简单的数据绑定程序来理解创建绑定的步骤。
代码清单11-1:创建绑定(源代码:第11章\Examples_11_1)
首先定义源对象,创建了一个MyData类,该类里面只有一个字符床属性Title,在这里要注意的是要实现绑定必须是属性类型,如果只是Title变量那么是实现不了绑定的。
MyData.cs文件主要代码 ---------------------------------------------------------------------------------------- public class MyData { public string Title { get; set; } }
然后我们再创建一个MyData类的对象,把该对象赋值给Page页面的DataContext属性,表示使用了这个对象作为该页面的数据上下文,在该页面里面就可以绑定MyData类对象的相关属性了。
MainPage.xaml.cs文件主要代码 ---------------------------------------------------------------------------------------- public MyData myData = new MyData { Title = "这是绑定的标题!" }; public MainPage() { this.InitializeComponent(); this.DataContext = myData; }
最后在界面上使用Binding实现UI和数据源属性之间的绑定关系,如在示例中把TextBlock控件的Text属性绑定到MyData对象的Title属性,这样就可以把Title属性的字符串显示在TextBlock控件上了。
MainPage.xaml文件主要代码 ---------------------------------------------------------------------------------------- <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <TextBlock Text="{Binding Title}" Margin="12,100,0,28" FontSize="50"></TextBlock> </Grid>
11.1.3 用元素值绑定
在上一小节里面我们的数据绑定源是一个自定义的数据对象,那么其实还可以使用UI控件的元素对象作为数据源,这样就可以实现了用元素值实现的数据绑定。用元素值进行绑定就是将某一个控件元素作为绑定的数据源,绑定的对象是控件元素,而绑定的数据源同时也是控件元素,这种绑定的方式,可以轻松地实现两个控件之间的值的交互影响。用元素值进行绑定时通过设置Binding的ElementName属性和Path属性来实现的,ElementName属性赋值为数据源控件的Name的值,Path 属性则赋值为数据源控件的某个属性,这个属性就是数据源控件的一个数据变化的反映。
在上一小节使用了“Binding Title”作为绑定扩展标志的语法,那么这个是最简单的绑定语法来的,其实我们可以利用Path属性实现更加丰富和灵活的绑定关联的语法,相关的语法情况如下所示:
(1)在最简单的情况下,Path属性值是要用于绑定的源对象的属性名,如 Path=PropertyName,那么{Binding Title}其实是{Binding Path=Title}的简写形式。
(2)在C#中可以通过类似语法指定属性的子属性。例如,子句 Path=ShoppingCart.Order 设置与对象或属性ShoppingCart的Order属性的绑定,也就是说ShoppingCart是你绑定数据源的属性,而Order则是ShoppingCart的属性,相当于是数据源的属性的属性。
(3)若要绑定到附加属性,应在附加属性周围放置圆括号。例如,若要绑定到附加属性Grid.Row,则语法是Path=(Grid.Row)。
(4)可以使用数组的索引器来实现数据的绑定。例如,子句 Path=ShoppingCart[0]将绑定设置为与数组属性的内部对应的索引的数值。
(5)可以在Path子句中混合索引器和子属性,例如,Path=ShoppingCart.ShippingInfo[MailingAddress,Street].
(6)在索引器内部,可以有多个由逗号分隔的索引器参数。可以使用圆括号指定每个参数的类型。例如, Path="[(sys:Int32)42,(sys:Int32)24]",其中sys映射到System命名空间。
(7)如果源为集合视图,则可以用斜杠“/”指定当前项。例如,子句 Path=/用于设置到视图中当前项的绑定。如果源为集合,则此语法指定默认集合视图的当前项。
(8)可以结合使用属性名和斜杠来遍历作为集合的属性。例如,Path=/Offices/ManagerName指定源集合的当前项,该源集合包含也作为集合的 Offices 属性。 其当前项是一个包含ManagerName属性的对象。
(9)也可以使用句点“.”路径绑定到当前源。例如,Text="{Binding}" 等效于 Text="{Binding Path=.}"。
下面给出控制圆的半径的示例:圆形的半径绑定到Slider控件的值,从而实现通过即时改变Slider控件的值来改变圆的大小。
代码清单11-2:控制圆的半径(源代码:第11章\Examples_11_2)
MainPage.xaml文件主要代码 ------------------------------------------------------------------------------------------------------------------ <StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <TextBlock FontSize="25" Name="textBlock1" Text="圆形的半径会根据slider控件的值而改变" /> <Slider Name="slider" Value="50" Maximum="400"/> <TextBlock FontSize="25" Name="textBlock2" Text="半径为:"/> <TextBlock Name="txtblk" Text="{Binding ElementName=slider, Path=Value}" FontSize="48"/> <Ellipse Height="{Binding ElementName=slider, Path=Value}" Width="{Binding ElementName=slider, Path=Value}" Fill="Red" Name="ellipse1" Stroke="Black" StrokeThickness="1"/> </StackPanel>
本文来源于《深入浅出Windows Phone 8.1 应用开发》
WP8.1 Runtime文章列表:http://www.cnblogs.com/linzheng/p/3998037.html
源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHb99O
欢迎关注我的微博@WP林政 微信公众号:wp开发(号:wpkaifa)
WP8.1技术交流群:372552293