Silverlight 解决Datagrid动态绑定列问题
上次的项目中遇到这样的一个需求,需要按照考试的明细名称列出成绩信息(就是正常主从表查询的行列转化差不多的功能)。因为SL也是刚接触,所以刚拿到手真是手足无措,如果在ASP.NET中还可以在后台去自定义一个DataTable去完成。但是悲催的SL里面没有这个DataTable对象了,正常绑定的数据源是后台的一个IEnumerable类型的集合。然后在XAML界面的DataGrid的控件中自己去定义数据源和相应的列名绑定字段,前面说了由于到底明细多少是未知的,这样咱们在界面就无法设置列了。虽然后台自己组合数据源列表绑定给界面也可以,让界面自动生成也可以,但是生成的列名就是结果集的字段名称(正常都是英文的,用户我想应该是看不懂的吧。)
由于本人当时查找了不少资料,还好找到了一些解决方案,不过现在也不记得是哪个前辈给的提醒了,不过真的感谢对此有帮助的大侠们。顺便小弟在此将自己的实现方式在这里做个简短的记录,已备遇到同样问题的人也有个帮助,欢迎指出解决的不好问题。
先看下实现的效果图:
本例的考试明细,我就选择一个类型来演示了,如果该考试有多个明细记录,就会产生多个列了。
现在先来说下成绩的表关系吧?
主表保存作答人以及试卷的主键ID,明细表列出该试卷的每个案例明细的得分情况。1:N的关系,本例因为测试 试卷只包含了跳跳记录。
好了,基本了解了需求以及我们的结构,接下来就来实现这个功能吧。
当初我是通过数据库的3个视图集合实现的,
视图一:界面字段的主表信息(撇开明细的数据),关联字段 考试ID,作答ID
视图二:动态明细的列表信息 关联字段:作答ID
视图三:考试的案例明细 :关键字段: 考试ID
接下来我们通过加载界面查出这3个视图的集合List<Rpt_Score_M> listm, List<Rpt_Score_CataD> listd,List<View_PracticeExampleCataDetail>PracticeExampleList
然后我们自己根据上面的结果自己组合需要的XML类型的字符串
1 #region XmlscoreDetail集合赋值 2 /// <summary> 3 /// XmlscoreDetail集合赋值 4 /// </summary> 5 /// <param name="listm">主表集合</param> 6 /// <param name="listd">明细表集合</param> 7 private void SetXmlscoreDetail(List<Rpt_Score_M> listm, List<Rpt_Score_CataD> listd) 8 { 9 int count = 1; //序号字段 10 StringBuilder xmlscoredetail = new StringBuilder(); 11 if (listm == null || listd == null) return; 12 //主数据排序 13 listm = listm.OrderByDescending(q => q.BeginTime).ToList(); 14 xmlscoredetail.Append("<?xml version='1.0' encoding='utf-8' ?>"); 15 xmlscoredetail.Append(" <Root>"); 16 foreach (var item in listm) 17 { 18 xmlscoredetail.Append(" <DataRow>"); 19 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "序号", count++, "序号")); 20 if (PracticeType == "1") 21 { 22 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "练习名称", item.Subject, "练习名称")); 23 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "练习科目", item.SystemName, "练习科目")); 24 } 25 else 26 { 27 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "试卷名称", item.Subject, "试卷名称")); 28 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "考试科目", item.SystemName, "考试科目")); 29 } 30 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "班级", item.OrgName, "班级")); 31 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "学员学号", item.StuNO, "学员学号")); 32 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "学员姓名", item.FullName, "学员姓名")); 33 34 //赋值案例列表 35 foreach (var temp in PracticeExampleList) 36 { 37 //查询当前的成绩明细是否有该案例的记录 38 var query = from s in listd 39 where s.DoExampleID == item.DoExampleID 40 group s.Score by new { DoExampleID = s.DoExampleID, CateName = s.CateName } into _gData 41 select new 42 { 43 Key = _gData.Key, 44 Score = _gData.Sum() 45 }; 46 var ditem = query.Where(q => q.Key.CateName == temp.CateName && q.Key.DoExampleID == item.DoExampleID).FirstOrDefault(); 47 if (ditem != null) 48 { 49 xmlscoredetail.Append(string.Format("<{0}> {1}分 </{2}>", temp.CateName, ditem.Score != null ? ditem.Score.Value : 0, temp.CateName)); 50 } 51 else 52 { 53 xmlscoredetail.Append(string.Format("<{0}> {1}分 </{2}>", temp.CateName, "0", temp.CateName)); 54 } 55 } 56 if (PracticeType == "1") 57 { 58 xmlscoredetail.Append(string.Format("<{0}> {1}分 </{2}>", "练习成绩", item.Scroe != null ? item.Scroe.Value : 0, "练习成绩")); 59 } 60 else 61 { 62 xmlscoredetail.Append(string.Format("<{0}> {1}分</{2}>", "考试成绩", item.Scroe != null ? item.Scroe.Value : 0, "考试成绩")); 63 } 64 //如果是练习增加下面字段 65 if (PracticeType == "1") 66 { 67 xmlscoredetail.Append(string.Format("<{0}> {1} </{2}>", "操作日期", item.BeginTime.ToString("yyyy-MM-dd"), "操作日期")); 68 } 69 xmlscoredetail.Append(" </DataRow>"); 70 } 71 xmlscoredetail.Append(" </Root>"); 72 XmlscoreDetail = xmlscoredetail.ToString(); 73 } 74 #endregion XmlscoreDetail集合赋值
#region 数据源赋值 /// <summary> /// 数据源赋值 /// </summary> /// <param name="xmlscoredetail">序列化的XML字符串</param> private void SetItems(string xmlscoredetail) { IEnumerable<IDictionary> result = GenerateData(XDocument.Parse(xmlscoredetail)); Items = DataSourceCreator.ToDataSource(result); PagerContext = new PagedCollectionView(Items); PagerContext.PageSize = _PageSize; } #endregion 数据源赋值
1 //根据XML类型的字符串获取字符串 2 private static IEnumerable<IDictionary> GenerateData(XDocument xml) 3 { 4 var element = xml.Descendants("DataRow"); 5 foreach (XElement item in element) 6 { 7 var dict = new Dictionary<object, object>(); 8 var nodes = item.Elements(); 9 foreach (XElement node in nodes) 10 { 11 dict[node.Name] = node.Value; 12 } 13 yield return dict; 14 } 15 }
界面的DataGrid 只要绑定生成的PagerContext 对象即可实现列名的自动绑定了。。
好了,这是我目前的实现方法,大家一起分享。欢迎大伙一起拍砖顺便指出改进!!!!