接着上面一篇,我们来讨论绑定集合等。
首先看一下可以进行绑定集合的控件属性,暂时我就不翻译了,因为翻译不好,还不如读英文呢。
Name | Description |
ItemsSource | Points to the collection that has all the objects that will be shown in the list. |
DisplayMemberPath | Identifies the property that will be used to creat the display text for each item. |
ItemTemplate | Providers a data template that will be used to create the visual appearance of each item.This property acts as a far more powerful replacement for DisplayMemberPath. |
ItemsPanel | Providers a template that will be used to create the layout container that holds all the items in the list. |
这里你可能会想,什么类型的集合可以绑定到ItemsSource属性呢?告诉你,只需要实现IEnumerable就可以,但是,实现这个借口的集合是只读的。如果你想编辑这个集合,例如允许插入和删除,你需要更多的工作,后面我们会介绍。
显示并且编辑集合项
首先定义个数据库交互契约
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace Domain.Entity
{
[DataContract]
public class Customer : INotifyPropertyChanged
{
private int _intCustomerId;
private string _strCustomerName;
private string _strCustomerCode;
private CustomerType _CustomerType;
private int _intCustomerTypeId;
[DataMember ]
public virtual int CustomerTypeId
{
get { return _intCustomerTypeId; }
set { _intCustomerTypeId = value; }
}
[DataMember ]
public virtual CustomerType CustomerType
{
get { return this._CustomerType; }
set
{
this._CustomerType = value;
OnPropertyChanged("CustomerType");
}
}
[DataMember]
public virtual int CustomerId
{
get { return this._intCustomerId; }
set
{
this._intCustomerId = value;
OnPropertyChanged("CustomerId");
}
}
[DataMember]
public virtual string CustomerName
{
get { return this._strCustomerName; }
set
{
this._strCustomerName = value; OnPropertyChanged("CustomerName");
}
}
[DataMember]
public virtual string CustomerCode
{
get { return _strCustomerCode; }
set
{
this._strCustomerCode = value;
OnPropertyChanged("CustomerCode");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
wcf定义接口
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Domain.Entity;
namespace WcfService
{
[ServiceContract]
public interface IServiceCustomer
{
[OperationContract]
Domain.Entity.Customer GetCustomer(int customerId);
[OperationContract]
IList < Domain.Entity.Customer > GetAll();
[OperationContract]
void Add(Domain.Entity.Customer customer);
[OperationContract]
string SayHello(SysUser sysUser);
}
}
实现这个接口
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using Domain.Entity;
using Common.Core;
using Common.Data;
namespace WcfService
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ServiceCustomer : IServiceCustomer
{
private CustomerDAO _customerDao;
Common.Core.Utility.NHibernateUtility _NHUtility;
MyValidator _myValidator;
public ServiceCustomer()
{
_NHUtility = new Common.Core.Utility.NHibernateUtility();
_customerDao = new CustomerDAO(_NHUtility.GetSession());
}
// Add more operations here and mark them with [OperationContract]
#region IServiceCustomer Members
public Domain.Entity.Customer GetCustomer( int customerId)
{
Domain.Entity.Customer objCustomer = new Domain.Entity.Customer();
return _customerDao.GetCustomerById(customerId);
}
#endregion
#region IServiceCustomer Members
public IList < Domain.Entity.Customer > GetAll()
{
IList < Domain.Entity.Customer > cs = _customerDao.GetAll();
return cs;
}
#endregion
#region IServiceCustomer Members
public void Add(Domain.Entity.Customer customer)
{
_customerDao.CreateCustomer(customer);
}
#endregion
#region IServiceCustomer Members
public string SayHello(SysUser sysUser)
{
_myValidator = (MyValidator)OperationContext.Current.Host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator;
return string .Format( " hello,{0},your password is {1}\n{2}{3} " , sysUser.UserName, sysUser.Password,
// _myValidator.ToString(),_myValidator.ToString() );
_myValidator.UserName ,_myValidator.Password );
}
#endregion
}
}
Silverlight客户端前台代码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class ="Silverlight.sldbdemo"
Width ="400" >
< ScrollViewer >
< StackPanel >
< Button x:Name ="btnGetCustomer" Content ="获取一个用户信息" Click ="btnGetCustomer_Click" ></ Button >
< Grid x:Name ="LayoutRoot" Background ="White" >
< Grid.ColumnDefinitions >
< ColumnDefinition />
< ColumnDefinition />
</ Grid.ColumnDefinitions >
< Grid.RowDefinitions >
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
</ Grid.RowDefinitions >
< TextBlock x:Name ="LblCustomerId" Grid.Column ="0" Grid.Row ="0" Text ="Customer Id" />
< TextBlock x:Name ="TxtCustomerId" Grid.Column ="1" Grid.Row ="0" Text ="{Binding CustomerId}" />
< TextBlock x:Name ="LblCustomerCode" Grid.Column ="0" Grid.Row ="1" Text ="Customer Code" />
< TextBlock x:Name ="TxtCustomerCode" Grid.Column ="1" Grid.Row ="1" Text ="{Binding CustomerCode}" />
< TextBlock x:Name ="LblCustomerName" Grid.Column ="0" Grid.Row ="2" Text ="用户名称" />
< TextBlock x:Name ="TxtCustomerName" Grid.Column ="1" Grid.Row ="2" Text ="{Binding CustomerName}" />
</ Grid >
< Button x:Name ="btnGetAllCustomer" Content ="获取全部用户信息" Click ="btnGetAllCustomer_Click" ></ Button >
< Grid x:Name ="customers" Background ="Gray" Grid.ColumnSpan ="2" Grid.Column ="0" Grid.Row ="3" >
< data:DataGrid x:Name ="dataGrid" CanUserResizeColumns ="true" CanUserSortColumns ="True"
AutoGenerateColumns ="False" ItemsSource ="{Binding}" >
< data:DataGrid.Columns >
< data:DataGridTextColumn Header ="Id" Binding ="{Binding CustomerId}" ></ data:DataGridTextColumn >
< data:DataGridTextColumn Header ="Code" Binding ="{Binding CustomerCode}" ></ data:DataGridTextColumn >
< data:DataGridTextColumn Header ="Name" Binding ="{Binding CustomerName}" ></ data:DataGridTextColumn >
</ data:DataGrid.Columns >
</ data:DataGrid >
</ Grid >
< StackPanel Grid.Column ="0" Grid.ColumnSpan ="2" Grid.Row ="4" >
< data:DataPager x:Name ="tempPager" DisplayMode ="FirstLastPreviousNextNumeric" HorizontalAlignment ="Left" VerticalAlignment ="Top"
Source ="{Binding Path=ItemsSource,ElementName=dataGrid}"
PageSize ="5"
></ data:DataPager >
</ StackPanel >
< Grid x:Name ="AddCustomer" Background ="White" Grid.Column ="0" Grid.ColumnSpan ="2" Grid.Row ="5" Height ="97" >
< Grid.ColumnDefinitions >
< ColumnDefinition Width ="0.5*" ></ ColumnDefinition >
< ColumnDefinition Width ="0.5*" ></ ColumnDefinition >
</ Grid.ColumnDefinitions >
< Grid.RowDefinitions >
< RowDefinition Height ="0.247*" ></ RowDefinition >
< RowDefinition Height ="0.247*" ></ RowDefinition >
< RowDefinition Height ="0.247*" ></ RowDefinition >
< RowDefinition Height ="0.258*" ></ RowDefinition >
</ Grid.RowDefinitions >
< TextBlock Text ="Customer Id" Grid.Column ="0" Grid.Row ="0" ></ TextBlock >
< TextBox x:Name ="customerId" Grid.Column ="1" Grid.Row ="0" ></ TextBox >
< TextBlock Text ="Custoemr Code" Grid.Column ="0" Grid.Row ="1" ></ TextBlock >
< TextBox x:Name ="customerCode" Grid.Column ="1" Grid.Row ="1" ></ TextBox >
< TextBlock Text ="Customer Name" Grid.Column ="0" Grid.Row ="2" ></ TextBlock >
< TextBox x:Name ="customerName" Grid.Column ="1" Grid.Row ="2" ></ TextBox >
< Button x:Name ="btnOk" Grid.Column ="0" Grid.Row ="3" Height ="25" Content ="添加用户Add Customer" Click ="btnOk_Click" ></ Button >
</ Grid >
< Button x:Name ="btnLoadData" Click ="btnLoadData_Click" Content ="加载数据" ></ Button >
< ListBox x:Name ="lstCustomers" ></ ListBox >
</ StackPanel >
</ ScrollViewer >
</ UserControl >
Silverlight客户端后台代码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Silverlight.ServiceCustomer;
using Domain.Entity;
namespace Silverlight
{
public partial class sldbdemo : UserControl
{
ServiceCustomerClient client;
SysUser _sysUser;
private int _customerId = 1 ;
public sldbdemo()
{
InitializeComponent();
client = new ServiceCustomerClient();
client.ClientCredentials.UserName.UserName = " adminstrator " ;
client.ClientCredentials.UserName.Password = " 123.com " ;
_sysUser = new SysUser() { UserName = " swb " , Password = " swb " };
client.SayHelloAsync(_sysUser);
client.SayHelloCompleted += new EventHandler < SayHelloCompletedEventArgs > (client_SayHelloCompleted);
}
void client_SayHelloCompleted( object sender, SayHelloCompletedEventArgs e)
{
try
{
MessageBox.Show(e.Result);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ex.InnerException.Message);
}
}
protected void GetCustomerById( int customerId)
{
try
{
client.GetCustomerCompleted += new EventHandler < GetCustomerCompletedEventArgs > (client_GetCustomerCompleted);
client.GetCustomerAsync(customerId );
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ex.InnerException.Message);
}
}
void client_GetCustomerCompleted( object sender, GetCustomerCompletedEventArgs e)
{
// Customer customer = new Customer() { CustomerId = 1, CustomerCode = "ss", CustomerName = "dddd" };
// LayoutRoot.DataContext = customer;
LayoutRoot.DataContext = e.Result;
}
protected void LoadCustomers()
{
try
{
client.GetAllCompleted += new EventHandler < GetAllCompletedEventArgs > (client_GetAllCompleted);
client.GetAllAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ex.InnerException.Message);
}
}
void client_GetAllCompleted( object sender, GetAllCompletedEventArgs e)
{
System.Windows.Data.PagedCollectionView page = new System.Windows.Data.PagedCollectionView(e.Result);
tempPager.Source = page;
dataGrid.ItemsSource = page;
}
private void btnOk_Click( object sender, RoutedEventArgs e)
{
try
{
client.AddCompleted += new EventHandler < System.ComponentModel.AsyncCompletedEventArgs > (client_AddCompleted);
Domain.Entity.Customer customer = new Domain.Entity.Customer()
{
CustomerId = int .Parse(customerId.Text),
CustomerCode = customerCode.Text,
CustomerName = customerName.Text
};
client.AddAsync( customer);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ex.InnerException.Message);
}
}
void client_AddCompleted( object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
LoadCustomers();
}
private void btnLoadData_Click( object sender, RoutedEventArgs e)
{
client.GetAllAsync();
client.GetAllCompleted += new EventHandler < GetAllCompletedEventArgs > (client_GetAllCompleted1);
}
void client_GetAllCompleted1( object sender, GetAllCompletedEventArgs e)
{
lstCustomers.ItemsSource = e.Result;
}
private void btnGetCustomer_Click( object sender, RoutedEventArgs e)
{
GetCustomerById(_customerId);
}
private void btnGetAllCustomer_Click( object sender, RoutedEventArgs e)
{
LoadCustomers();
}
}
}
效果图
你会看到后面的listbox中,数据显示的全部都是Domain.Entity.Customer,没有显示成我们想要的某一栏的值,这就是因为在代码中我们使用了lstCustomers.ItemsSource = e.Result;第一种绑定集合的属性,这时候就需要第二种绑定集合的属性 DisplayMemberPath="CustomerName"登场了。
其实实现上面的效果,你可以有三条途径:
1)设置控件的DisplayMemberPath属性为一个对象的属性名称,例如:DisplayMemberPath="CustomerName",效果如下图
2)重写对象的ToString()方法,提供一些有用的信息,设置可以显示几个属性,因为默认绑定使用的就是对象的tostring方法
{
return string .Format ( " 用户代码:{0} | 用户姓名:{1} " ,CustomerCode,CustomerName );
}
属性就不用修改了,还是<ListBox x:Name="lstCustomers" ></ListBox>,效果如下图
3)提供一个数据模板,这样你可以显示任何排列好的对象属性值,后面将会讲到这种做法。
到这里你可能又需要两外一个功能了,就是点击一个list中的item,在下面显示一下详细信息。你可以响应listbox的SelectionChanged事件,在事件代码中写上
{
gridCustomerDetails.DataContext = lstCustomers.SelectedItem;
}
前台设置为
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
< Grid x:Name ="gridCustomerDetails" Background ="White" >
< Grid.ColumnDefinitions >
< ColumnDefinition />
< ColumnDefinition />
</ Grid.ColumnDefinitions >
< Grid.RowDefinitions >
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
< RowDefinition Height ="20" />
</ Grid.RowDefinitions >
< TextBlock x:Name ="LblCustomerIdd" Grid.Column ="0" Grid.Row ="0" Text ="Customer Id" />
< TextBlock x:Name ="TxtCustomerIdd" Grid.Column ="1" Grid.Row ="0" Text ="{Binding CustomerId}" />
< TextBlock x:Name ="LblCustomerCoded" Grid.Column ="0" Grid.Row ="1" Text ="Customer Code" />
< TextBlock x:Name ="TxtCustomerCoded" Grid.Column ="1" Grid.Row ="1" Text ="{Binding CustomerCode}" />
< TextBlock x:Name ="LblCustomerNamed" Grid.Column ="0" Grid.Row ="2" Text ="用户名称" />
< TextBlock x:Name ="TxtCustomerNamed" Grid.Column ="1" Grid.Row ="2" Text ="{Binding CustomerName}" />
</ Grid >
效果如下图
插入和删除集合中的项
你通过服务接口获取的数据集合可能是各种各样的,array、list等,但是在客户端他们的存储类型都是 System.Collections.ObjectModel.ObservableCollection,当你返回一个集合的时候,自动翻译类型。
这种设计是因为客户端不知道服务器会返回什么类型的集合,Silverlight假设使用 System.Collections.ObjectModel.ObservableCollection类型是安全的,因为 System.Collections.ObjectModel.ObservableCollection相对array、dictionary来说都有更多的功能。
在sl前台加上一个button
<Button x:Name="btnDelCustomer" Content="删除一个用户" Click="btnDelCustomer_Click"></Button>
然后再后台写上
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
System.Collections.ObjectModel.ObservableCollection < Customer > customers = (System.Collections.ObjectModel.ObservableCollection < Customer > )lstCustomers.ItemsSource ;
customers .Remove ((Customer )lstCustomers.SelectedItem );
}
在页面上就会看到效果,这只是从集合中删除,并没有从后端数据库删除,你加载一下的话,数据还是在的。如果要实现真正的数据操作,还是要利用wcf的服务来实现数据库的操作。
LINQ是.NET 3.5中的一个新型的数据查询方式,就是对对象集合的查询,更加面向对象的查询。它的查询结果是实现了IEnumerable<T>接口的,所以使用LINQ查询的结果也是可以绑定到ItemsSource的。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
where c.CustomerName = = " dd "
select c;
lstCustomers.ItemsSource = maths;
不像list或者ObserverableCollection,IEnumerable<T>接口没有提供添加或者删除方法。如果你需要的话,可以使用接口的toarray和tolist方法转化为有操作方法的集合,如果更加需要的话,还可以进一步搞成ObserverableCollection集合。
List<Customer > list = maths.ToList<Customer>();
接下来我们要实现的这么一种效果,就先下列出来所有的用户类型,然后选中类型之后,再显示当前类型的全部用户姓名,选中用户姓名之后,再显示用户详细信息。
我们要添加一个用户类型的定义,在wcf中要添加一个获取全部类型的接口。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ComponentModel;
using System.Runtime.Serialization;
using Iesi.Collections.Generic;
namespace Domain.Entity
{
[DataContract]
public class CustomerType : INotifyPropertyChanged
{
private string _strCustomerTypeName;
private int _intCustomerTypeId;
private ISet<Customer> _customers;
[DataMember ]
public virtual int CustomerTypeId
{
get { return this._intCustomerTypeId; }
set
{
this._intCustomerTypeId = value;
OnPropertyChanged("CustomerTypeId");
}
}
[DataMember]
public virtual string CustomerTypeName
{
get { return this._strCustomerTypeName; }
set
{
this._strCustomerTypeName = value; OnPropertyChanged("CustomerTypeName");
}
}
[DataMember]
public virtual ISet <Customer> Customers
{
get { return this._customers; }
set
{
this._customers = value;
OnPropertyChanged("Customers");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public IList < Customer > GetCustomerByTypeId( int typeId)
{
return _customerDao.GetCustomerByTypeId(typeId);
}
public IList < CustomerType > GetAllCustomerType()
{
return _customerTypeDao.GetAll();
}
#endregion
插入一个有用的连接,Silverlight 的 .NET Framework 类库,里面是Silverlight客户端可以使用的.NET类库。
稳扎稳打Silverlight(22) - 2.0通信之调用WCF服务, 对传输信息做加密