动态加载列可以说是一个从无到有的过程,如果只是网页上的DataGrid实现那就太无味了,有趣的在这里,这个页面上连带着一大堆的数据库表的查询修改,尤其是做着做着发现数据表设计有缺陷,需要的数据竟然只有出口没有入口,想想也是醉了,对业务不熟悉真心的杀不起。其实吧这个蛮好玩的,就像玩捉迷藏藏得那个人叫做nothing,再后来我又遇到了Multiple-births(多胞胎),一个页面上涉及到了六七张数据库表,里边的字段名虽然不一样,可它就是达到了百分之七八十的相似度!来吧,先看看页面上的操作流程
一、操作流程
1.页面一加载是这个样子的
2.输入招标编号后,一点击确定是这个样子的
这里已经把DataGrid动态加载出来了,如果你想问为什么不在页面加载前就定义了DataGrid呢?好吧,没有招标编号这个参数,它只会报错、报错、报错!或者提前先定义好几套DataGrid的js,在输入了招标编号后根据招标编号动态调用?在网上查阅到很多人都是这样做的,不过我得定义多少套呢,况且我还不知道它会有多少列,每列叫什么。把上边的图划分一下,大家再看看
有了1,才有2和3,有了2才有了3中的4,这样说好像很傻的样子,可以略过,goon
3.选择投标商后,即可显示我们需要的信息
评委还没有对该投标商评过分,所以“专家评分Id”、评分项“暗标”等是空的。上图只是它很平静的表面,它的真实面目如下图,其中没有算计投标商以及联系起投标商和DataGrid二者用到的表。D表的显示数据可以有多个列,这里只用了一条演示
4.填入分数后,可以用咱们上篇博客写到的对DataGrid的编辑功能,提交到后台了
当然,更换了组合框中的投标商后,DataGrid中的信息也跟着变动
二、代码实现
1.Html页面上的代码很简单
<body>2.js中的实现代码比较多,精简了一些,下边是我用到的主要函数
<div style="margin-top: auto; margin-left: 50px;">
<div class="easyui-panel" title="评分信息" style="width: 1142px;">
<div style="margin: 10px 20px; float: left">
@* 1.加载搜索框 *@
请输入招标编号:@Html.TextBox("BidRecordId")
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-search',plain:true" onclick="Ok()">确定</a>
</div>
<div id="dropDownList" style="margin: 12px 50px; display: none;">
请选择投标商:
<input id="companyName" class="easyui-combobox" name="companyName" value="--请选择--" data-option="
method:'get',
panelWidth:350,
panelHeight:'auto',
formatter:formatItem
">
</div>
</div>
</div>
@*主体内容部分*@
<div id="contentAreas" style="margin-top: 10px; margin-left: 50px; width: 1142px; display: none">
<div class="easyui-panel" title="评分项管理" style="width: 1142px;">
@* 加载按钮 *@
<div id="btnAreas" style="margin-bottom: 5px; margin-top: 10px;">
<div id="tb" style="width: auto; height: auto">
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-save',plain:true" onclick="save()">保存</a>
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-undo',plain:true" onclick="reject()">撤销</a>
<a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-search',plain:true" onclick="getChanges()">获取修改行</a>
</div>
</div>
<div>
<table id="dg" class="easyui-datagrid" style="width: 1140px; height: 400px; padding-left: 200px;">
</table>
</div>
</div>
</div>
</body>
var editIndex = undefined; //用来获取编辑的行号var bidRecordId; //定义一个变量,用来保存招标编号var columnsAll = new Array(); //定义一个新的列集合,用来保存返回的数据//显示隐藏的信息function Ok() { if ($("#BidRecordId").val() == "") { alert("请输入招标编号!"); $("#BidRecordId").select(); } else { //显示组合框 document.getElementById("dropDownList").style.display = ""; //获取搜索框中的内容 bidRecordId = document.getElementById("BidRecordId").value; //2.动态加载组合框中的数据,写法有误,返回函数功能不能实现 $('#companyName').combobox({ url: '/BidManager/GetTUserByZUser?BidRecordId=' + bidRecordId, valueField: 'Value', textField: 'Text' }); //显示主体内容页 document.getElementById("contentAreas").style.display = ""; //动态加载表头中的数据,ajax调用后台方法 load_dg(); //当组合框中的文本更换时,获取组合框中所对应的Id值,并加载表格中的数据 $('#companyName').combobox({ onSelect: function () { bidRecorderId = $('#companyName').combobox('getValue').trim(); //获取组合框中文本所对应的id值 //TODO:添加一个弹出框,在有未保存信息的情况下,提醒用户是否保存 if (editIndex != undefined) { alert("您修改的数据将不被保存!"); } editIndex = undefined; //确保在组合框中的文本更换时,对应的datagrid的编辑功能可用 //id值为空,则只传递招标编号,否则把“招标编号”和“投标商id”拼接成字符串 if (bidRecorderId != "[object HTMLInputElement]") { var key = bidRecordId + "," + bidRecorderId; } else { var key = bidRecordId } //2.加载数据并显示DataGrid中的值 $.ajax({ url: '/BidManager/GetSpecialistByZBid?Key=' + key, success: function (data) { //加载完数据后,切割评分项 var array = new Array; //将加载到的值,重新赋值传给datagrid for (var i = 0; i < data.length; i++) { var obj = new Object(); obj.SpecialistId = data[i].SpecialistId; obj.ItemScoreId = data[i].ItemScoreId; obj.SpecialistName = data[i].SpecialistName; obj.Score = data[i].Score; //或者用obj['Scores']=data[i].Score; obj.BidRecorderId = bidRecorderId; //评分的分数不为空,则对评分项分数进行切割 if (data[i].ItemScores != null) { //将整体的评分项,切割成单个的评分项 var ItemScores = data[i].ItemScores; //获取所有评分项的评分Id及分数 var scoreEvery = new Array(); //定义一个数组来接收每个评分Id及其分数 scoreEvery = ItemScores.split("##"); //将切割得到的各个评分项Id及其分数,放入定义好的数组中 //将单个的评分项id与分数值切割开 for (var j = 0; j < scoreEvery.length; j++) { var score = new Array(); //定义一个数组,用来装载评分项分数切割后的值 score = scoreEvery[j].split("#"); //将一个评分项分数的id与分数值分隔开 obj[score[0].toLowerCase()] = score[1]; //把切割好的分数值对(id+分数)添加到数组中 } }; //将对象装载到数组中 array.push(obj); } $('#dg').datagrid('loadData', array); } }) } }) };}//动态加载表头中的数据,ajax调用后台方法function load_dg() { $.post('/BidManager/ShowBidProperties?BidRecordId=' + bidRecordId, function (jsonObj) { //如果返回的数据不为空,则添加遍历该数据集合 if (jsonObj.length > 0) { for (var i = 0; i < jsonObj.length; i++) { //把返回的数据封装到一个对象中 var col = {} col["title"] = jsonObj[i].FieldText; col["field"] = jsonObj[i].FieldValue; col["editor"] = jsonObj[i].Editor; col["width"] = 150; col["align"] = 'center' //col["hidden"] = jsonObj[i].Hidden; //把这个对象添加到列集合中 columnsAll.push(col); } //重新加载表格 $('#dg').datagrid({ height: 500, singleSelect: true, url: '', fit: true, singleSelect: true, toolbar: '#tb', method: 'get', columns: [columnsAll], onClickRow: onClickRow, //单击事件 }).datagrid("reload"); } else { $.messager.alert('提示信息', '没有可用数据,请联系管理员!', 'warning'); } }, "JSON");}//保存按钮,多条数据一起提交function save() { if (endEditing()) { //获取更新更改的行的集合 row = $("#dg").datagrid('getChanges'); //DataGrid的更该行为不为0 if (row.length) { var array = new Array; for (var i = 0; i < row.length; i++) { var obj = new Object(); obj.SpecialistId = row[i].SpecialistId; obj.ItemScoreId = row[i].ItemScoreId; obj.SpecialistName = row[i].SpecialistName; obj.Score = row[i].Score; obj.BidRecorderId = row[i].BidRecorderId; //拼接所有评分项的值 var valueAll = ""; for (var h = 3; h < columnsAll.length - 1; h++) { var title = columnsAll[h].field.toUpperCase(); //获取这列的列Id var field = row[i][columnsAll[h].field]; //获取单元格的值 //获取所有评分项的id与值 if (valueAll == "" || valueAll == null) { valueAll += title + "#" + field; } else { valueAll += "##" + title + "#" + field; } } obj.ItemScores = valueAll; array.push(obj); } $.ajax( { type: 'POST', url: "/BidManager/UpdateOrAddItemScore", data: { arrayList: JSON.stringify(array), }, success: function (data) { if (data != "") { $.messager.alert('提示', '保存成功!'); $('#dg').datagrid('reload'); // 重新载入当前页面数据 } else { $.messager.alert('提示信息', '保存失败,请联系管理员!', 'warning'); } } }); } else //如果没有修改数据,则提醒用户 { $.messager.alert('提示信息', '您还没有修改信息!', 'warning'); } } editIndex = undefined;}3.Controller中的代码就是查询并定义DataGrid的表头,其中有四列是固定的,即A、B、C、E四个表对应的表头是固定的,A、B两表对应的列在实际中会被隐藏,D表对应的列根据实际评分项的数量自动扩充或缩减。因为每一列的属性都是固定的,所以我新建了一个专门的ViewModel类用来管理列属性(这个ViewModel放在服务端)
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Runtime.Serialization;namespace LFBidSystem.ViewModel{ [DataContract] public class TableHeaderViewModel { /*表头描述 * 1.FieldValue:键值 * 2.FieldText:显示名称 * 3.Hidden:是否隐藏 */ [DataMember] public string FieldValue; [DataMember] public string FieldText; [DataMember] public bool Hidden; [DataMember] public string Editor; }}Controller中加载表头的方法如下
string bidRecordId;
#region 加载表头信息 + 王静娜 2015-5-28 10:31:54
public ActionResult ShowBidProperties()
{
//表头实体集合
List<TableHeaderViewModel> listHeaderVM = new List<TableHeaderViewModel>();
//隐藏的表头列“评分项得分编号”
TableHeaderViewModel judgeHeader1Hide = new TableHeaderViewModel
{
FieldValue = "SpecialistId",
FieldText = "专家Id",
Hidden = true
};
listHeaderVM.Add(judgeHeader1Hide);
//隐藏的表头列“评分项得分编号”
TableHeaderViewModel judgeHeader2Hide = new TableHeaderViewModel
{
FieldValue = "ItemScoreId",
FieldText = "专家评分Id",
Hidden = true
};
listHeaderVM.Add(judgeHeader2Hide);
//第一列“评委”
TableHeaderViewModel judgeHeaderFirst = new TableHeaderViewModel
{
FieldValue = "SpecialistName",
FieldText = "评委",
Hidden = false
};
listHeaderVM.Add(judgeHeaderFirst);
//第二列及倒数第二列之前,各评分项遍历
//获取页面上的招标编号,并转化成Guid格式的数据类型
bidRecordId = Request.Params["BidRecordId"];
Guid recordId = new Guid(bidRecordId);
//根据招标编号,获取所对应的所有评分项信息,评分名称作为表头
List<BidJudgeViewModel> listBidJudge = iBidJudgeService.GetBidJudge(recordId);
foreach (var item in listBidJudge)
{
TableHeaderViewModel JudgeHeader = new TableHeaderViewModel();
JudgeHeader.FieldValue = item.JudgeId.ToString();
JudgeHeader.FieldText = item.JudgeItemName;
JudgeHeader.Hidden = false;
JudgeHeader.Editor = "text";
listHeaderVM.Add(JudgeHeader);
}
//最后一列“总分”
TableHeaderViewModel judgeHeaderLast = new TableHeaderViewModel
{
FieldValue = "Score",
FieldText = "总分",
Editor = "text",
Hidden = false
};
listHeaderVM.Add(judgeHeaderLast);
//将封装的表头信息返回给前台
return Json(listHeaderVM, JsonRequestBehavior.AllowGet);
}
#endregion
这样动态加载列基本上就实现了,里边比较麻烦的是把Controller中查询到的表头信息显示到页面上,这部分在js中实现。由于数据库表字段中有一列(D表)用到了值拼接,所以循环切割拼接在所难免,从而也导致了列显示更加复杂一些,都做出来后整个感觉都好了。。。
三篇DataGrid的总结已经写完,有失误的地方,欢迎指正~