但是問題來了,不同科系的同學的科目是不一樣的,那麼我們在資料庫設計的時候通常是把學生、某科成績作為一條記錄,那麼這個時候我們就需要做一個行轉列的邏輯處理了。
解決方案:
使用GridView來產生表單,這個實現起來會比較麻煩,如果要在列表裡面顯示連結就更不可能了;
產生html再輸出到頁面中,這個實現起來比較靈活、方便;
準系統點:
動態產生表頭;
資料進行分頁;
查詢資料;
對每個成績進行超連結,查看明細;
頁面代碼 複製代碼 代碼如下:<div id="dataDiv1">
<asp:Literal ID="labtable" runat="server"></asp:Literal>
<div class="toolBlock" style="border-top:solid 1px #C0CEDF; padding-top:5px">
<bw:VirtualPager ID="VirtualPager1" runat="server" ItemsPerPage="10" OnPageIndexChanged="VirtualPager1_PageIndexChanged" />
</div>
</div>
後台代碼(產生html字串) 複製代碼 代碼如下:/// <summary>
/// table方式載入考核成績.
/// Step1:通過年月來擷取唯一的批次.
/// Step2:產生表頭.
/// Step3:開始迴圈每個使用者.
/// Step4:迴圈每個使用者的考核項.
/// </summary>
protected void BindTable()
{
labtable.Text = string.Empty;
//通過年月來擷取唯一的批次.
string year = DropDownImportYear.SelectedValue;
string month = DropDownImportMonth.SelectedValue;
string group_KH_Date = year + month;
GroupService groupService = new GroupService();
DataTable dtGroup = groupService.GetByTemplateCodeAndGroup_KH_Date(TemplateCode, group_KH_Date);
if (dtGroup.Rows.Count > 0)
{
Guid groupID = (Guid)DbUtils.ToGuid(dtGroup.Rows[0]["ID"]);
int groupStutas = DbUtils.ToInt32(dtGroup.Rows[0]["GroupStutas"].ToString());
DataTable dtCells = personalGradeService.GetDistinctTemplateItemNameByGroupID(groupID);
GroupID = groupID.ToString();
if (dtCells.Rows.Count > 0)
{
int cellsCount = 0;//考核項數.
StringBuilder strtable = new StringBuilder();
strtable.AppendFormat("<table cellpadding=\"0\" cellspacing=\"0\" class=\"tblClass\">");
strtable.AppendFormat("<tr>");
strtable.AppendFormat("<th>使用者名稱</th>< /span>");
cellsCount = dtCells.Rows.Count;
for (int i = 0; i < cellsCount; i++)
{
strtable.AppendFormat("<th>{0}</th>", dtCells.Rows[i]["Name"].ToString());
}
strtable.AppendFormat("</tr>");
DataTable dtGradeData = GetData(cellsCount);
int cursor = 1;//表示一個使用者的第一條記錄.
string userName = string.Empty;
string realName = string.Empty;
for (int i = 0; i<dtGradeData.Rows.Count; i++)
{
if (cursor == 1)
{
userName = dtGradeData.Rows[i]["UserName"].ToString();
realName = dtGradeData.Rows[i]["RealName"].ToString();
strtable.AppendFormat("<td width=\"12%\">{0}</td>", realName);
}
string id = dtGradeData.Rows[i]["ID"].ToString();
string templateItemCode = dtGradeData.Rows[i]["TemplateItemCode"].ToString();
strtable.AppendFormat("<td width=\"50px\">");
string GradeData = dtGradeData.Rows[i]["GradeData"].ToString();
if (!string.IsNullOrEmpty(GradeData) && GradeData != "0")
{
GradeData=Math.Round(decimal.Parse(GradeData), 2).ToString();
//轉換成兩位小數
}
strtable.AppendFormat("{0}", GradeData);
//未發布的成績才能修改
if (groupStutas != (int)Botwave.MRPS.Constants.GroupStutas.FinishPush)
{
strtable.AppendFormat("<br /><a style=\"text-decoration:underline\" class=\"thickbox\" href='UserGradeDataEdit.aspx?ID={0}&BeModifer={1}&KeepThis=true&TB_iframe=true&height=250&width=500'>", id, userName);
strtable.AppendFormat("<img src=\"../res/gradeedit.gif\" align=\"baseline\" title=\"修改成績\" />");
strtable.AppendFormat("</a>");
}
strtable.AppendFormat(" <a target=\"_blank\" style=\"text-decoration:underline\" href='http://www.cnblogs.com/CheckObjectManager/pages/LogScoreChangeDetail.aspx?GroupId={0}&TemplateCode={1}&TemplateItemCode={2}&UserName={3}&returnUrl='>", groupID, TemplateCode, templateItemCode, userName);
strtable.AppendFormat("<img src=\"../res/gradelog.gif\" align=\"baseline\" title=\"查看日誌\" />");
strtable.AppendFormat("</a>");
strtable.AppendFormat("</td>");
if (cursor < cellsCount)
cursor++;
else
{
strtable.AppendFormat("</tr>");
cursor = 1;
}
}
strtable.AppendFormat("</table>");
labtable.Text = strtable.ToString();
}
}
}
幾個輔助方法(如何處理好分頁問題,這就關係到cellsCount參數的使用了,cellsCount表示科目數) 複製代碼 代碼如下:protected void btnSearch_Click(object sender, EventArgs e)
{
SearchNow = true;
VirtualPager1.CurrentPageIndex = 1;
BindTable();
}
protected void VirtualPager1_PageIndexChanged(object sender, Botwave.Web.Controls.PageChangedEventArgs e)
{
BindTable();
}
/// <summary>
/// 擷取考核成績.
/// </summary>
/// <returns></returns>
private DataTable GetData(int cellsCount)
{
int nRecordCount = 0;
string condition = "";
string filterName = txtUserName.Text.Trim();//姓名搜尋.
StringBuilder sb = new StringBuilder();
sb.AppendFormat(" GroupID ='{0}'", GroupID);
if (!string.IsNullOrEmpty(filterName))
sb.AppendFormat(" AND (UserName like '%{0}%' OR RealName like '%{0}%')", filterName);
condition = sb.ToString();
if (SearchNow)//當在很多頁的時候,或者是最後一頁,這個時候來點擊查詢,就會報錯了CurrentPageIndex,這個做法就是為了防止這個.
VirtualPager1.CurrentPageIndex = 0;
DataTable dt = personalGradeService.GetGradeData(VirtualPager1.CurrentPageIndex, VirtualPager1.ItemsPerPage * cellsCount, condition, ref nRecordCount);
VirtualPager1.TotalRecordCount = nRecordCount / cellsCount;
VirtualPager1.DataBind();
SearchNow = false;//要重新複製.
return dt;
}
商務邏輯(分頁) 複製代碼 代碼如下:public System.Data.DataTable GetGradeData(int currentPageIndex, int pageSize, string condition, ref int nRecordCount)
{
string fieldShow = " UserID,TemplateCode,TemplateItemCode,GradeData,ID,UserName,RealName ";
string fieldOrder = " UserName ASC,TemplateItemCode ASC ";
string where = condition;
if (String.IsNullOrEmpty(where))
{
where = "1=1";
}
return IBatisDbHelper.GetPagedList("dbo.vw_UserGradeData", "ID", currentPageIndex, pageSize, fieldShow, fieldOrder, where, ref nRecordCount);
}
注意事項:
在使用<asp:Literal ID="labtable" runat="server"></asp:Literal>來在頁面輸出html來顯示表單的話,要注意字串的長度,如果html太長的話,就會出錯了,因為Literal的有8000個字元的限制的;
在資料庫中對資料進行好排序,這樣才能保證資料跟表頭是一一對應的;
這裡有個前提,那就是查詢出來的資料都是包含同等多的記錄的,比如同學A和同學B的科目是一樣多的;因為不一樣多,那這個動態表單就沒什麼意義了。如果真的有不同,也是可以做出來的,但是會麻煩一點;