今天我们讨论的是Silverlight3中的数据绑定,内容来自 《》的读后感。

  数据绑定提供了一种,从对象中获取信息,然后显示在你的应用程序的界面上,同时不需要写冗长的代码就可以完成所有的工作的方式。通常情况下,富客户端提供两种绑定方式,不仅可以从兑现获取数据,显示到界面上,也可以将界面的数据传回给对象。
  Silverlight是不允许客户端直接使用ADO.NET直接连接数据库,进行数据库操作的。只能通过代理的方式操作数据库,通过第三方,例如:webservice、wcf、ado.net data service、ric service等服务性的方式。(文/)
  1、绑定到数据对象
  例如现在又一个Customer的实体对象
  
数据对象

  1. [DataContract]
     
  2. public class Customer
     
  3. {
     
  4. private int _intCustomerId;
     
  5. private string _strCustomerName;
     
  6. private string _strCustomerCode;
     
  7. [DataMember]
     
  8. public virtual int CustomerId
     
  9. {
     
  10. get { return this._intCustomerId; }
     
  11. set { this._intCustomerId = value; }
     
  12. }
     
  13. [DataMember]
     
  14. public virtual string CustomerName
     
  15. {
     
  16. get { return this._strCustomerName; }
     
  17. set { this._strCustomerName = value; }
     
  18. }
     
  19. [DataMember]
     
  20. public virtual string CustomerCode
     
  21. {
     
  22. get { return _strCustomerCode; }
     
  23. set { this._strCustomerCode = value; }
     
  24. }
     
  25. }
     
复制代码

想要达到下图的一种效果

 

附件:
你需要才可以下载或查看附件。没有帐号?

  就需要下面这样的代码,在页面中可以用 Text="{Binding CustomerId}"来实现。
  
前台页面

  1. <Grid x:Name="LayoutRoot" Background="White">
     
  2. <Grid.ColumnDefinitions>
     
  3. <ColumnDefinition/>
     
  4. <ColumnDefinition/>
     
  5. </Grid.ColumnDefinitions>
     
  6. <Grid.RowDefinitions>
     
  7. <RowDefinition Height="20"/>
     
  8. <RowDefinition Height="20"/>
     
  9. <RowDefinition Height="20"/>
     
  10. <RowDefinition Height="20"/>
     
  11. <RowDefinition Height="20"/>
     
  12. <RowDefinition Height="20"/>
     
  13.  
  14. </Grid.RowDefinitions>
     
  15. <TextBlock x:Name="LblCustomerId" Grid.Column="0" Grid.Row="0" Text="Customer Id"/>
     
  16. <TextBlock x:Name="TxtCustomerId" Grid.Column="1" Grid.Row="0" Text="{Binding CustomerId}"/>
     
  17. <TextBlock x:Name="LblCustomerCode" Grid.Column="0" Grid.Row="1" Text="Customer Code"/>
     
  18. <TextBlock x:Name="TxtCustomerCode" Grid.Column="1" Grid.Row="1" Text="{Binding CustomerCode}"/>
     
  19. <TextBlock x:Name="LblCustomerName" Grid.Column="0" Grid.Row="2" Text="用户名称"/>
     
  20. <TextBlock x:Name="TxtCustomerName" Grid.Column="1" Grid.Row="2" Text="{Binding CustomerName}"/>
     
  21.  
  22.  
  23. </Grid>
     
复制代码

后台代码

绑定到对象

  1. void client_GetCustomerCompleted(object sender, GetCustomerCompletedEventArgs e)
     
  2. {
     
  3. Customer customer = new Customer() { CustomerId = 1, CustomerCode = "ss", CustomerName = "dddd" };
     
  4. LayoutRoot.DataContext = customer;
     
  5. }
     
复制代码
2、将数据对象存储为资源
  提供一篇文章,供大家参考:
  首先要在类代码中存在一个资源对象,
代码
  1. namespace Silverlight
     
  2. {
     
  3. public class Users
     
  4. {
     
  5. public string Firstname { get; set; }
     
  6. public string Lastname { get; set; }
     
  7. }
     
  8. public partial class DataBindingDemo : UserControl
     
  9. {
     
  10. public DataBindingDemo()
     
  11. {
     
  12. InitializeComponent();
     
  13.  
  14. }
     
  15. }
     
  16. }
     
复制代码
在控件中存储资源
  1. <UserControl x:Class="Silverlight.DataBindingDemo"
     
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     
  4. xmlns:local="clr-namespace:Silverlight"
     
  5. Width="400" Height="300">
     
  6. <UserControl.Resources>
     
  7.  
  8. <local:Users x:Key="SingleUser" Firstname="virus" Lastname="ssss"></local:Users>
     
  9. </UserControl.Resources>
     
  10. <Grid x:Name="LayoutRoot" Background="White">
     
  11. <TextBox Text="{Binding Path=Firstname,Source={StaticResource SingleUser}}"></TextBox>
     
  12. </Grid>
     
  13.  
  14. </UserControl>
     
复制代码
上面的红色部分的xmlns:local="clr-namespace:Silverlight"是定义资源的命名空间,
  1.   <UserControl.Resources>
     
  2.  
  3. <local:Users x:Key="SingleUser" Firstname="virus" Lastname="ssss"></local:Users>
     
  4. </UserControl.Resources>
     
复制代码
是定义一个资源
  1.   <TextBox Text="{Binding Path=Firstname,Source={StaticResource SingleUser}}"></TextBox>
     
复制代码
是绑定到控件,源是SingleUser,绑定的具体属性是 Firstname。如果是绑定一个属性的话,每次都需要设置Source的值,如果是绑定到一个Grid上面的话,可以使用<Grid Name="gridUsers" DataContext="{StaticResource SingleUser}">来绑定。
  3、可编辑的双向绑定
  到这里你可能想要知道,如果我在界面上修改一个值,会发生什么呢?例如你修改了界面上面的文本框的值,文本框的值绑定了一个对象的属性,在内存中的对象属性会改变吗?
  实际上,内存中的对象属性没有任何变化,因为Silverlight默认使用单向绑定。
  System.Windows.Data.BindingMode枚举量中定义了全部的绑定类型,如下表:
Name

Description

OneWay
单向绑定
 

当对象属性改变的时候,绑定对象就会改变

TwoWay
双向绑定
 

当源对象属性改变的时候,绑定对象会改变;反过来,绑定对象的改变也会影响源对象属性的改变。

OneTime
一次性绑定
 

绑定对象在第一次初始化的时候显示对象的属性,后面不会随着对象属性的改变而改变,这种适用于你确定对象的属性几乎不会改变的情况下。

  1.   <TextBox Text="{Binding Firstname, Mode=TwoWay}"></TextBox>
     
复制代码
如果你使用了双向绑定,如果你修改了textbox的值,当你的鼠标焦点一离开textbox之后(焦点在两外一个控件,或者点击一个按钮),内存中的对象属性Firstname就会发生改变,执行属性的set。
使用了双向绑定之后,焦点一离开控件之后就会触发内存对象的改变,但是有的时候我们想精确控制,而不是等焦点移除的时候,例如:输入框在用户输入的同时就进行,而不是等用户焦点移出输入框,你可以在代码中调用 BindingExpression.UpdateSource();
代码
  1. private void txtFirstname_TextChanged(object sender, TextChangedEventArgs e)
     
  2. {
     
  3. BindingExpression expression = txtFirstname.GetBindingExpression(TextBox.TextProperty);
     
  4. expression.UpdateSource();
     
  5. }
     
复制代码
使用上面的代码,你就可以在用户进入文本框和输入的时候就强迫文本框更新源对象的属性值。如果你全部的控件都是用这样的更新方式,你就可以禁用 Silverlight的自动更新功能,设置UpdateSourceTrigger属性的值为Explicit。
代码
  1. <TextBox x:Name="txtFirstname"
     
  2. Text="{Binding Path=Firstname,Source={StaticResource SingleUser}, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
     
  3. TextChanged="txtFirstname_TextChanged"></TextBox>
     
复制代码
在Silverlight中UpdateSourceTrigger有两个属性值可以设置:Default和Explicit。
4、数据验证 Validation
数据验证将在下一篇中重点讲解。先提供一个实例代码下载:DataValidation
验证的话,就需要Silverlight客户端和wcf服务端共享类库,共享实体类,因为服务端的实体类虽然被序列化到客户端,但是只能序列化状态信息,就是成员,方法之类的不会序列化的,而且就算序列化过来,也没有什么用,运行环境context都不一样了,没有什么意思。所以可能会用到客户端和服务端共享类库,可以参考下面的文章。

5、绑定到一个数据服务

更复杂的数据绑定中,数据可能是从外部服务获取的。这里的外部服务使用wcf来提供,下面的代码假定你已经了解wcf,如果不了解的可以看老徐的博客或者google一些资料来看。数据库操作部分使用NHibernate 2.1.2完成。
首先定义数据交互契约
实体代码

  1. using System;
     
  2. using System.Collections.Generic;
     
  3. using System.Linq;
     
  4. using System.Text;
     
  5. using System.ServiceModel;
     
  6. using System.ComponentModel;
     
  7. using System.Runtime.Serialization;
     
  8.  
  9. namespace Domain.Server
     
  10. {
     
  11. [DataContract]
     
  12. public class Customer : INotifyPropertyChanged
     
  13. {
     
  14. private int _intCustomerId;
     
  15. private string _strCustomerName;
     
  16. private string _strCustomerCode;
     
  17. [DataMember]
     
  18. public virtual int CustomerId
     
  19. {
     
  20. get { return this._intCustomerId; }
     
  21. set
     
  22. {
     
  23. this._intCustomerId = value;
     
  24. OnPropertyChanged("CustomerId");
     
  25. }
     
  26. }
     
  27. [DataMember]
     
  28. public virtual string CustomerName
     
  29. {
     
  30. get { return this._strCustomerName; }
     
  31. set
     
  32. {
     
  33. this._strCustomerName = value; OnPropertyChanged("CustomerName");
     
  34. }
     
  35. }
     
  36. [DataMember]
     
  37. public virtual string CustomerCode
     
  38. {
     
  39. get { return _strCustomerCode; }
     
  40. set
     
  41. {
     
  42. this._strCustomerCode = value;
     
  43. OnPropertyChanged("CustomerCode");
     
  44. }
     
  45. }
     
  46.  
  47. #region INotifyPropertyChanged Members
     
  48.  
  49. public event PropertyChangedEventHandler PropertyChanged;
     
  50.  
  51. #endregion
     
  52. private void OnPropertyChanged(string propertyName)
     
  53. {
     
  54. if (PropertyChanged != null)
     
  55. {
     
  56. PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
     
  57. }
     
  58. }
     
  59. }
     
  60. }
     
复制代码

wcf服务代码

代码

  1. using System;
     
  2. using System.Linq;
     
  3. using System.Runtime.Serialization;
     
  4. using System.ServiceModel;
     
  5. using System.ServiceModel.Activation;
     
  6. using System.Collections.Generic;
     
  7. using System.Collections.ObjectModel;
     
  8. using System.Text;
     
  9. using System.Data.SqlClient;
     
  10. using System.Data;
     
  11. using Domain.Server;
     
  12. using Common.Core;
     
  13. using Common.Data;
     
  14. namespace WcfService
     
  15. {
     
  16. public class ServiceCustomer : IServiceCustomer
     
  17. {
     
  18. private CustomerDAO _customerDao;
     
  19. Common.Core.Utility.NHibernateUtility _NHUtility;
     
  20. MyValidator _myValidator;
     
  21. public ServiceCustomer()
     
  22. {
     
  23. _NHUtility = new Common.Core.Utility.NHibernateUtility();
     
  24. _customerDao = new CustomerDAO(_NHUtility.GetSession());
     
  25.  
  26. //string name = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;
     
  27. }
     
  28. // Add more operations here and mark them with [OperationContract]
     
  29.  
  30. public Domain.Server.Customer GetCustomer(int customerId)
     
  31. {
     
  32.  
  33. Domain.Server.Customer objCustomer = new Domain.Server.Customer();
     
  34.  
  35. return _customerDao.GetCustomerById(customerId);
     
  36. }
     
  37.  
  38. }
     
  39. }
     
复制代码

 
Silverlight的前台代码
代码
  1. <Grid x:Name="LayoutRoot" Background="White">
     
  2. <Grid.ColumnDefinitions>
     
  3. <ColumnDefinition/>
     
  4. <ColumnDefinition/>
     
  5. </Grid.ColumnDefinitions>
     
  6. <Grid.RowDefinitions>
     
  7. <RowDefinition Height="20"/>
     
  8. <RowDefinition Height="20"/>
     
  9. <RowDefinition Height="20"/>
     
  10. <RowDefinition Height="20"/>
     
  11. <RowDefinition Height="20"/>
     
  12. <RowDefinition Height="20"/>
     
  13.  
  14. </Grid.RowDefinitions>
     
  15. <TextBlock x:Name="LblCustomerId" Grid.Column="0" Grid.Row="0" Text="Customer Id"/>
     
  16. <TextBlock x:Name="TxtCustomerId" Grid.Column="1" Grid.Row="0" Text="{Binding CustomerId}"/>
     
  17. <TextBlock x:Name="LblCustomerCode" Grid.Column="0" Grid.Row="1" Text="Customer Code"/>
     
  18. <TextBlock x:Name="TxtCustomerCode" Grid.Column="1" Grid.Row="1" Text="{Binding CustomerCode}"/>
     
  19. <TextBlock x:Name="LblCustomerName" Grid.Column="0" Grid.Row="2" Text="用户名称"/>
     
  20. <TextBlock x:Name="TxtCustomerName" Grid.Column="1" Grid.Row="2" Text="{Binding CustomerName}"/>
     
  21.  
  22.  
  23. </Grid>
     
复制代码
Silverlight的后台代码
代码
  1. using System;
     
  2. using System.Collections.Generic;
     
  3. using System.Linq;
     
  4. using System.Net;
     
  5. using System.Windows;
     
  6. using System.Windows.Controls;
     
  7. using System.Windows.Documents;
     
  8. using System.Windows.Input;
     
  9. using System.Windows.Media;
     
  10. using System.Windows.Media.Animation;
     
  11. using System.Windows.Shapes;
     
  12. using Silverlight.ServiceCustomer;
     
  13.  
  14. namespace Silverlight
     
  15. {
     
  16. public partial class sldbdemo : UserControl
     
  17. {
     
  18. ServiceCustomerClient client;
     
  19. SysUser _sysUser;
     
  20. public sldbdemo()
     
  21. {
     
  22. InitializeComponent();
     
  23. client = new ServiceCustomerClient();
     
  24. GetCustomerById(1);
     
  25. }
     
  26. protected void GetCustomerById(int customerId)
     
  27. {
     
  28. try
     
  29. {
     
  30. client.GetCustomerCompleted += new EventHandler<GetCustomerCompletedEventArgs>(client_GetCustomerCompleted);
     
  31. client.GetCustomerAsync( customerId);
     
  32. }
     
  33. catch (Exception ex)
     
  34. {
     
  35. MessageBox.Show(ex.Message + ex.InnerException.Message);
     
  36. }
     
  37. }
     
  38.  
  39. void client_GetCustomerCompleted(object sender, GetCustomerCompletedEventArgs e)
     
  40. {
     
  41. LayoutRoot.DataContext = e.Result;
     
  42. }
     
  43. }
     
  44. }
     
复制代码