在前面 WPF的TreeView数据绑定基础 文章中已经对 WPF 的TreeView的原理,在本文继续深入使用WPF的TreeView,本文将不对TreeView的基础介绍,主要深入从数据库中绑定数据,通过泛型装载数据表,然后循环成TreeView的节点,同时才用 Webservice 跨域传输TreeView树型数据,在 Webservice 可以清晰地看到Xml装载数据的树形结构,下面是详细介绍。
先在 WPF的TreeView数据绑定基础 的示例基础上建立一个 Webservice 服务应用程序(用以提供数据服务给WPF程序),本示例命名为 CityService 。
数据库部分
数据表在本示例数据库中建立了三个关联表,分别是CityData(一级城市列表)、CityItemData(城市子级分区)、CityChildItem(城市分区的地点),三个表应对TreeView建立三级目录,通过关联主键来实现数据分层循环绑定数据显示。下图是三个数据表关联结构显示。
示例采用DataSet数据集,将三个表加入在数据集中映射成数据操作方法,同时加入关联数据查询语句,在CityData中采用默认的查询生成即可;在 CityItemData 中的查询采用 SELECT CityItemId, CityItemName FROM CityItemData WHERE (CityId = @CityId) 关联 CityData 中的 CityId 列即下图的GetDataById(@CityId)方法;在CityChildItem表中的查询采用 SELECT CityChildItemId, CityChildItemName FROM CityChildItem WHERE (CityItemId = @CityItemId) 关联 CityItemData 表中的 CityItemId 字段即GetDataByCityItemId(@CityItemId)方法。
Webservice数据传输(可以参考 ASP.NET WebService应用程序基础 )
在CityService建立CityInfo.cs类,CityInfo类对应的是三个数据表的数据字段,可以根据实际情况建立属性,比如有些数据属性列不需要读取出来的则不需要建立,除此以外还建立一个List<CityInfo> ChildItem用以作子级节点。在建立ControlData.cs类为数据操作类,在ControlData类中对DataSetCity数据集的数据操作方法再次优化包装方法以便在项目其它地方调用。
using System.Collections.Generic; /**//// <summary> ///CityInfo - WPF的TreeView从数据库绑定数据 /// </summary> public class CityInfo ...{ public int CityId ...{ get; set; } public string CityName ...{ get; set; } public int CityItmeId ...{ get; set; } public string CityItmeName ...{ get; set; } public int CityChildItemId ...{ get; set; } public string CityChildItemName ...{ get; set; } public List<CityInfo> ChildItem ...{ get; set; } ControlData.cs 代码 复制 using System; using System.Collections.Generic; using CityService.DataSetCityTableAdapters; using System.Data; using CityService; /**//// <summary> ///ControlData - WPF的TreeView数据库绑定数据 /// </summary> public class ControlData ...{ 数据表类传入实例化#region 数据表类传入实例化 /**//// <summary> /// CityData /// </summary> public CityDataTableAdapter CityData ...{ ...{ return new CityDataTableAdapter(); /**//// <summary> /// CityItemData /// </summary> public CityItemDataTableAdapter CityItemData ...{ ...{ return new CityItemDataTableAdapter(); /**//// <summary> /// CityChildItem /// </summary> public CityChildItemTableAdapter CityChildItem ...{ ...{ return new CityChildItemTableAdapter(); #endregion /**///////////////////////////////////////////////////// 数据库表查询方法传入#region 数据库表查询方法传入 /**//// <summary> /// CityDatas() ->城市列表 /// </summary> /// <returns></returns> public DataSetCity.CityDataDataTable CityDatas() ...{ return CityData.GetData(); /**//// <summary> /// CityDataItme(int id) ->城市子集 /// </summary> /// <param name="id"></param> /// <returns></returns> public DataSetCity.CityItemDataDataTable CityDataItem(int id) ...{ return CityItemData.GetDataById(id); /**//// <summary> /// CityChildItemById(int id) ->城市分区子集 /// </summary> /// <param name="id"></param> /// <returns></returns> public DataSetCity.CityChildItemDataTable CityChildItemById(int id) ...{ return CityChildItem.GetDataByCityItemId(id); #endregion /**///////////////////////////////////////////////////////// /// <summary> /// Loop DataRow /// CityList() -> 城市列表 将三个表的数据查询DataRow循环 /// 载入List<CityInfo>CityList()中。 /// </summary> /// <returns></returns> public List<CityInfo> CityList() ...{ //一级/First-Root List<CityInfo> list = new List<CityInfo>(); foreach (DataRow row in CityData.GetData()) ...{ CityInfo myCity = new CityInfo(); myCity.CityId = Convert.ToInt32(row["CityId"]); myCity.CityName = row["CityName"].ToString(); //二级/Second-Root List<CityInfo> lists = new List<CityInfo>(); foreach (DataRow itme in CityDataItem(Convert.ToInt32(row["CityId"]))) ...{ CityInfo items = new CityInfo(); items.CityId = Convert.ToInt32(itme["CityItemId"]); items.CityName = itme["CityItemName"].ToString(); lists.Add(items); //三级/Third-Root List<CityInfo> list02 = new List<CityInfo>(); foreach (DataRow cityItem in CityChildItemById(Convert.ToInt32(items.CityId))) ...{ CityInfo childItem = new CityInfo(); childItem.CityId = Convert.ToInt32(cityItem["CityChildItemId"]); childItem.CityName = cityItem["CityChildItemName"].ToString(); list02.Add(childItem); items.ChildItem = list02; myCity.ChildItem = lists; list.Add(myCity); return list; 接着在Webservice类中将ControlData类的CityList()方法在包装一次提供给外部其他项目访问使用,启动http://localhost:5985/Service1.asmx Webservice可以看见Citylist方法调用后返回XML树形结构数据。WPF引用Webservice绑定数据然后在WPF的TreeViewTest项目中引入Webservice服务(添加服务引用),接着在MainWindow.xaml.cs中加入using TreeViewTest.CityServiceReference;,将Service1SoapClient ws = new Service1SoapClient();实例化,把ws.Citylist()数据方法绑定给treeView.ItemsSource。此时运行程序即可看见TreeView已经成功的绑定到三级数据。总结本文示例可以分为两层,一层是数据服务端Webservice程序,一层则是WPF程序,在整个项目中CityService作为数据服务端程序,WPF就是一个客户端程序接受数据绑定操作。也可以将数据层的数据和操作类全部合并到WPF同一个项目里面来,这样就直接在同一个项目中读取数据操作,Webservice可以不需要了。提示:示例项目需要先启动Webservice服务器端,然后再编译执行WPF的TreeView程序才能成功,否则无法连接服务端。本文示例项目知识点:数据库数据表建立DataSet数据集结合存储过程查询使用Webservice服务端程序使用,可以参考(ASP.NET WebService应用程序基础、WebService与Silverlight数据交互)WPF程序,即是本文的中心TreeView绑定数据库数据
using System; using System.Collections.Generic; using CityService.DataSetCityTableAdapters; using System.Data; using CityService; /**//// <summary> ///ControlData - WPF的TreeView数据库绑定数据 /// </summary> public class ControlData ...{ 数据表类传入实例化#region 数据表类传入实例化 /**//// <summary> /// CityData /// </summary> public CityDataTableAdapter CityData ...{ ...{ return new CityDataTableAdapter(); /**//// <summary> /// CityItemData /// </summary> public CityItemDataTableAdapter CityItemData ...{ ...{ return new CityItemDataTableAdapter(); /**//// <summary> /// CityChildItem /// </summary> public CityChildItemTableAdapter CityChildItem ...{ ...{ return new CityChildItemTableAdapter(); #endregion /**///////////////////////////////////////////////////// 数据库表查询方法传入#region 数据库表查询方法传入 /**//// <summary> /// CityDatas() ->城市列表 /// </summary> /// <returns></returns> public DataSetCity.CityDataDataTable CityDatas() ...{ return CityData.GetData(); /**//// <summary> /// CityDataItme(int id) ->城市子集 /// </summary> /// <param name="id"></param> /// <returns></returns> public DataSetCity.CityItemDataDataTable CityDataItem(int id) ...{ return CityItemData.GetDataById(id); /**//// <summary> /// CityChildItemById(int id) ->城市分区子集 /// </summary> /// <param name="id"></param> /// <returns></returns> public DataSetCity.CityChildItemDataTable CityChildItemById(int id) ...{ return CityChildItem.GetDataByCityItemId(id); #endregion /**///////////////////////////////////////////////////////// /// <summary> /// Loop DataRow /// CityList() -> 城市列表 将三个表的数据查询DataRow循环 /// 载入List<CityInfo>CityList()中。 /// </summary> /// <returns></returns> public List<CityInfo> CityList() ...{ //一级/First-Root List<CityInfo> list = new List<CityInfo>(); foreach (DataRow row in CityData.GetData()) ...{ CityInfo myCity = new CityInfo(); myCity.CityId = Convert.ToInt32(row["CityId"]); myCity.CityName = row["CityName"].ToString(); //二级/Second-Root List<CityInfo> lists = new List<CityInfo>(); foreach (DataRow itme in CityDataItem(Convert.ToInt32(row["CityId"]))) ...{ CityInfo items = new CityInfo(); items.CityId = Convert.ToInt32(itme["CityItemId"]); items.CityName = itme["CityItemName"].ToString(); lists.Add(items); //三级/Third-Root List<CityInfo> list02 = new List<CityInfo>(); foreach (DataRow cityItem in CityChildItemById(Convert.ToInt32(items.CityId))) ...{ CityInfo childItem = new CityInfo(); childItem.CityId = Convert.ToInt32(cityItem["CityChildItemId"]); childItem.CityName = cityItem["CityChildItemName"].ToString(); list02.Add(childItem); items.ChildItem = list02; myCity.ChildItem = lists; list.Add(myCity); return list;
接着在Webservice类中将ControlData类的CityList()方法在包装一次提供给外部其他项目访问使用,启动http://localhost:5985/Service1.asmx Webservice可以看见Citylist方法调用后返回XML树形结构数据。
WPF引用Webservice绑定数据
然后在WPF的TreeViewTest项目中引入Webservice服务(添加服务引用),接着在MainWindow.xaml.cs中加入using TreeViewTest.CityServiceReference;,将Service1SoapClient ws = new Service1SoapClient();实例化,把ws.Citylist()数据方法绑定给treeView.ItemsSource。此时运行程序即可看见TreeView已经成功的绑定到三级数据。
总结本文示例可以分为两层,一层是数据服务端Webservice程序,一层则是WPF程序,在整个项目中CityService作为数据服务端程序,WPF就是一个客户端程序接受数据绑定操作。也可以将数据层的数据和操作类全部合并到WPF同一个项目里面来,这样就直接在同一个项目中读取数据操作,Webservice可以不需要了。提示:示例项目需要先启动Webservice服务器端,然后再编译执行WPF的TreeView程序才能成功,否则无法连接服务端。
本文示例项目知识点: