当前位置:   article > 正文

C# Web控件与数据感应之 填充 HtmlTable

C# Web控件与数据感应之 填充 HtmlTable

目录

关于 HtmlTable

HtmlTable与BaseDataList的区别

准备数据源

范例运行环境

FillTable 方法

设计与实现

模板样例输出

Automatic 模式填充

         DynamicRows 模式填充

StaticRows 模式填充

小结


关于 HtmlTable

数据感应也即数据捆绑,是一种动态的,Web控件与数据源之间的交互,HtmlTable 控件表示为一个服务器控件,隶属于 System.Web.UI.HtmlControls 集合,对于客户端输出即 table 标签元素,table 表格的主要作用就是数据输出 ,本文将介绍 C# 实现操作 HtmlTable 服务器控件实现数据集表数据的轻量化输出与显示。

HtmlTable与BaseDataList的区别

HtmlTable 与诸如 DataGrid、GridView 都可用于数据输出 ,主要区别在于:

(1)前者以属于System.Web.UI.HtmlControls 集合,后者 Microsoft.Web.UI.WebControls 集合

(2)HtmlTable 可实现 table 元素的一些操作,如行、列、单元格及样式设置,而 BaseDataList 除可实现 HtmlTable 的基本控制外,还可以绑定数据源、绑定事件、绑定列控件等更加强大的功能。

(3)对于数据集合访问 HtmlTable 通过 Rows ,列集合为 Cells;而 BaseDataList  通过 Items ,列集合为 Colums。

准备数据源

我们在 MS SQL Server 创建 pub_ChinaPay(支付状态代码表),其结构如下表:

序号字段名类型说明
1valuechar(4)支付状态代码,唯一键
2textnvarchar(14)状态名称
3sortidsmallint排序号

执行如下 创建表的 SQL 语句:

  1. CREATE TABLE [dbo].[pub_ChinaPay](
  2. [value] [char](4) NOT NULL,
  3. [text] [nvarchar](14) NOT NULL,
  4. [sortid] [smallint] NULL,
  5. CONSTRAINT [PK_pub_ChinaPay] PRIMARY KEY CLUSTERED
  6. (
  7. [value] ASC
  8. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  9. ) ON [PRIMARY]
  10. GO

执行如下SQL语句,创建一些数据:

  1. insert into pub_ChinaPay(value,text,sortid) values('****','默认状态',1)
  2. insert into pub_ChinaPay(value,text,sortid) values(' ','待支付',2)
  3. insert into pub_ChinaPay(value,text,sortid) values('1001','消费交易成功',3)
  4. insert into pub_ChinaPay(value,text,sortid) values('1003','退款提交成功',4)
  5. insert into pub_ChinaPay(value,text,sortid) values('1005','退款撤销成功',5)
  6. insert into pub_ChinaPay(value,text,sortid) values('0003','交易失败',6)
  7. insert into pub_ChinaPay(value,text,sortid) values('6666','微信退款申请成功',7)

通过查询分析器,执行查询SQL语句,显示如下图:

最后我们将数据填充到 DataReader ,并生成对应的二维数组。

范例运行环境

操作系统: Windows Server 2019 DataCenter

数据库:Microsoft SQL Server 2016

.net版本: .netFramework4.0 或以上

开发工具:VS2019  C#

FillTable 方法

设计与实现

FillTable 方法主要是通过 object[,] 二维对象数组数据源进行提取并呈现在 HtmlTable 表格控件上,其参数设置见下表:

序号参数名类型说明
1tbSystem.Web.UI.HtmlControls.HtmlTable要输出的 HtmlTable 对象
2ftFillType

填充模式枚举:

public enum FillType
 { Automatic,DynamicRows,

StaticRows
}

后续将讲解这些模式的区别

3SpaceInEmptyCellbool对于空字符串输出,是否替换为&nbsp 输出以达到更好的显示效果
4MinClearRowsCountint当输出数据行为空时,清除模板表格行的阀值,设为0,则表示全部清空,不显示输出表格的任何元素
5refStartRowIdint指定数据输出的起始行
6refCopyRowIdint指定要复制哪一行的格式进行输出
7allowToHTMLbool是否允许将数据解析为HTML样式输出,默认为 false

GetReaderData 方法可以访问数据库数据表进行查询结果的提取,并转化为 object[,] 二维数组,其参数设置见下表:

序号参数名类型说明
1DbServerTypestring目前支持 "oracle"、 "dm8",其它字符串均视为 MS SQL Server
strConnstring对应数据库的连接字符串
2_sqlstring要执行的SQL语句命令行
3parasArrayList

要赋值的参数对象,逐个添加到ArrayList里,请注意参数为实体数据参数对象,如 MS SQL Server ,请传递如下代码:

ArrayList.Add(new SqlParameter("参数名",参数值)); 

4hastitlebool输出是否包含字段列标题
5ctCommandType

System.Data.CommandType 枚举,可包括:

StoredProcedure(存储过程)
TableDirect(直接表查询)
Text(文本查询)该值为默认值

GetReaderData 方法实现代码如下:

  1. int RowsCount = 0;
  2. int ErrorNum = 0;
  3. string ErrorMessage = "";
  4. public object[,] GetReaderData(string DbServerType,string strConn,string _sql,ArrayList paras,bool hastitle,CommandType ct)
  5. {
  6. if((DbServerType.ToLower()=="")||(DbServerType.ToLower()=="sqlserver"))
  7. {
  8. SqlConnection Conn = new SqlConnection(strConn );
  9. SqlCommand Cmd = new SqlCommand();
  10. Cmd.CommandType=ct;
  11. Cmd.Connection = Conn;
  12. SqlDataReader myDr;
  13. Cmd.CommandText =_sql;
  14. if(paras!=null)
  15. {
  16. for(int i=0;i<paras.Count;i++)
  17. {
  18. Cmd.Parameters.Add((SqlParameter)paras[i]);
  19. }
  20. }
  21. try
  22. {
  23. Conn.Open();
  24. myDr = Cmd.ExecuteReader();
  25. ArrayList rowdata = new ArrayList();
  26. int _fieldcount=myDr.FieldCount;
  27. Object[] colvalues = new Object[_fieldcount];
  28. for(int i=0;i<_fieldcount;i++)
  29. {
  30. colvalues[i]=myDr.GetName(i);
  31. }
  32. if(hastitle)
  33. rowdata.Add(colvalues);
  34. while(myDr.Read())
  35. {
  36. Object[] values = new Object[_fieldcount];
  37. myDr.GetValues(values);
  38. rowdata.Add(values);
  39. RowsCount++;
  40. }
  41. myDr.Close();
  42. object[,] rv=new object[rowdata.Count,_fieldcount];
  43. for(int i=0;i<rowdata.Count;i++)
  44. {
  45. for(int j=0;j<_fieldcount;j++)
  46. {
  47. rv[i,j]=((object[])rowdata[i])[j];
  48. }
  49. }
  50. return rv;
  51. }
  52. catch (SqlException e)
  53. {
  54. ErrorMessage=e.Message;
  55. return null;
  56. }
  57. finally
  58. {
  59. Conn.Close();
  60. Conn.Dispose();
  61. }
  62. }//sqlserver
  63. if(DbServerType.ToLower()=="oracle")
  64. {
  65. OracleConnection Conn = new OracleConnection(strConn );
  66. OracleCommand Cmd = new OracleCommand();
  67. Cmd.Connection = Conn;
  68. OracleDataReader myDr;
  69. Cmd.CommandText =_sql;
  70. if(paras!=null)
  71. {
  72. for(int i=0;i<paras.Count;i++)
  73. {
  74. Cmd.Parameters.Add((OracleParameter)paras[i]);
  75. }
  76. }
  77. try
  78. {
  79. Conn.Open();
  80. myDr = Cmd.ExecuteReader();
  81. ArrayList rowdata = new ArrayList();
  82. int _fieldcount=myDr.FieldCount;
  83. Object[] colvalues = new Object[_fieldcount];
  84. for(int i=0;i<_fieldcount;i++)
  85. {
  86. colvalues[i]=myDr.GetName(i);
  87. }
  88. if(hastitle)
  89. rowdata.Add(colvalues);
  90. while(myDr.Read())
  91. {
  92. Object[] values = new Object[_fieldcount];
  93. myDr.GetValues(values);
  94. rowdata.Add(values);
  95. RowsCount++;
  96. }
  97. myDr.Close();
  98. object[,] rv=new object[rowdata.Count,_fieldcount];
  99. for(int i=0;i<rowdata.Count;i++)
  100. {
  101. for(int j=0;j<_fieldcount;j++)
  102. {
  103. rv[i,j]=((object[])rowdata[i])[j];
  104. }
  105. }
  106. return rv;
  107. }
  108. catch (OracleException e)
  109. {
  110. ErrorMessage=e.Message;
  111. return null;
  112. }
  113. finally
  114. {
  115. Conn.Close();
  116. Conn.Dispose();
  117. }
  118. }//oracle
  119. if (DbServerType.ToLower() == "dm8")
  120. {
  121. DmConnection Conn = new DmConnection(strConn);
  122. DmCommand Cmd = new DmCommand();
  123. Cmd.CommandType = ct;
  124. Cmd.Connection = Conn;
  125. DmDataReader myDr;
  126. Cmd.CommandText = _sql;
  127. if (paras != null)
  128. {
  129. for (int i = 0; i < paras.Count; i++)
  130. {
  131. Cmd.Parameters.Add((DmParameter)paras[i]);
  132. }
  133. }
  134. try
  135. {
  136. Conn.Open();
  137. myDr = Cmd.ExecuteReader() as DmDataReader;
  138. ArrayList rowdata = new ArrayList();
  139. int _fieldcount = myDr.FieldCount;
  140. Object[] colvalues = new Object[_fieldcount];
  141. for (int i = 0; i < _fieldcount; i++)
  142. {
  143. colvalues[i] = myDr.GetName(i);
  144. }
  145. if (hastitle)
  146. rowdata.Add(colvalues);
  147. while (myDr.Read())
  148. {
  149. Object[] values = new Object[_fieldcount];
  150. myDr.GetValues(values);
  151. rowdata.Add(values);
  152. RowsCount++;
  153. }
  154. myDr.Close();
  155. object[,] rv = new object[rowdata.Count, _fieldcount];
  156. for (int i = 0; i < rowdata.Count; i++)
  157. {
  158. for (int j = 0; j < _fieldcount; j++)
  159. {
  160. rv[i, j] = ((object[])rowdata[i])[j];
  161. }
  162. }
  163. return rv;
  164. }
  165. catch (DmException e)
  166. {
  167. ErrorMessage = e.Message;
  168. return null;
  169. }
  170. finally
  171. {
  172. Conn.Close();
  173. Conn.Dispose();
  174. }
  175. }//dm8
  176. return null;
  177. }//getreaddata

FillTable 方法实现代码如下:

  1. ArrayList paras=new ArrayList();
  2. string refSql="";
  3. bool hastitle=false;
  4. System.Data.CommandType ct=System.Data.CommandType.Text;
  5. public void FillTable(HtmlTable tb, FillType ft, bool SpaceInEmptyCell, int MinClearRowsCount, int refStartRowId,int refCopyRowId,bool allowToHTML)
  6. {
  7. object[,] ReaderData = GetReaderData("SqlServer","您的连接串","",paras,hastitle,ct);
  8. if (ReaderData == null && RowsCount==0)
  9. {
  10. while (tb.Rows.Count > MinClearRowsCount)
  11. {
  12. tb.Rows.RemoveAt(tb.Rows.Count - 1);
  13. }
  14. return;
  15. }
  16. if (ft == FillType.Automatic || ft==FillType.DynamicRows || ft==FillType.StaticRows)
  17. {
  18. if (ft == FillType.Automatic)
  19. {
  20. int addcells = ReaderData.GetLength(1) - tb.Rows[0].Cells.Count;
  21. for (int i = 0; i < tb.Rows.Count; i++)
  22. {
  23. for (int j = 0; j < addcells; j++)
  24. {
  25. HtmlTableCell tc = new HtmlTableCell();
  26. if (allowToHTML == true)
  27. {
  28. tc.Attributes.Add("ByHTML", "true");
  29. }
  30. tb.Rows[i].Cells.Add(tc);
  31. }
  32. }
  33. if (tb.Rows.Count == 2)
  34. {
  35. for (int j = 0; j < ReaderData.GetLength(1); j++)
  36. {
  37. string _fieldname = ReaderData[0, j].ToString();
  38. tb.Rows[0].Cells[j].InnerText = _fieldname;
  39. }
  40. }
  41. }
  42. int startRowID = tb.Rows.Count - 1;
  43. int copyRowID = 0;
  44. if (ft == FillType.StaticRows)
  45. {
  46. if (HasTitle == true)
  47. {
  48. startRowID = tb.Rows.Count > 1 ? 1 : 0;
  49. }
  50. else
  51. {
  52. startRowID = 0;
  53. }
  54. }
  55. if (refStartRowId != -1) startRowID = refStartRowId;
  56. if (refCopyRowId != -1) copyRowID = refCopyRowId;
  57. for (int i = (HasTitle == true ? 1 : 0); i < ReaderData.GetLength(0); i++)
  58. {
  59. if (startRowID>tb.Rows.Count-1) break;
  60. for (int j = 0; j < ReaderData.GetLength(1); j++)
  61. {
  62. if (j > tb.Rows[copyRowID].Cells.Count - 1) break;
  63. HtmlTableCell td = tb.Rows[startRowID].Cells[j];
  64. if (td.Attributes["ByHTML"] == null)
  65. {
  66. td.InnerText = ReaderData[i, j].ToString();
  67. }
  68. else
  69. {
  70. td.InnerHtml = allowToHTML == true ? (ReaderData[i, j].ToString()) : ReaderData[i, j].ToString();;
  71. }
  72. if (td.InnerText == "" && SpaceInEmptyCell == true) td.InnerHtml="&nbsp;";
  73. }
  74. if (i == ReaderData.GetLength(0)-1) break;
  75. if (ft == FillType.Automatic || ft == FillType.DynamicRows)
  76. {
  77. HtmlTableRow tr = new HtmlTableRow();
  78. tb.Rows.Add(tr);
  79. for (int k = 0; k < tb.Rows[copyRowID].Cells.Count; k++)
  80. {
  81. HtmlTableCell prv_tc = tb.Rows[startRowID].Cells[k];
  82. HtmlTableCell tc = new HtmlTableCell();
  83. tr.Cells.Add(tc);
  84. CloneStyles(prv_tc, tc);
  85. }
  86. }
  87. startRowID ++;
  88. }
  89. }
  90. }//fill table
  91. void CloneStyles(HtmlControl obj, HtmlControl newobj)
  92. {
  93. IEnumerator keys = obj.Style.Keys.GetEnumerator();
  94. while (keys.MoveNext())
  95. {
  96. String key = (String)keys.Current; newobj.Style[key] = obj.Style[key];
  97. }
  98. IEnumerator keys2 = obj.Attributes.Keys.GetEnumerator();
  99. while (keys2.MoveNext())
  100. {
  101. String key = (String)keys2.Current; newobj.Attributes[key] = obj.Attributes[key];
  102. }
  103. }

模板样例输出

在方法设计的章节里介绍了 FillType (即填充类型的枚举)

Automatic 模式填充

全自动填充,表示行、列均不固定,全由SQL查询结果动态输出,仅设置首行首列的样式即可,如下图:

 前端代码示例 :

  1. <table id="tjTable" runat="server" align="center" border="1" style="width: 700px; border:1px solid #000000;border-collapse:collapse">
  2. <tr><td>标题</td></tr>
  3. <tr>
  4. <td>
  5. &nbsp;</td>
  6. </tr>
  7. </table>

调用示例如下代码:

  1. string refSQL = "select value,text,sortid from pub_chinaPay order by sortid";
  2. FillTable(tjTable, FillType.Automatic, true, 0, 1, 1);

输出结果如下图 

可以看到行列完全由SQL语句决定进行原始输出,行与列均为动态输出 。 

DynamicRows 模式填充

动态行填充,表示行输出不固定,已预知列的输出,仅需要设置首行标题列和数据行的样式即可,如下图:

 前端代码示例 :

  1. <table id="tjTable" runat="server" align="center" border="1" style="width: 700px; border:1px solid #000000;border-collapse:collapse">
  2. <tr>
  3. <td>
  4. 状态代码</td>
  5. <td>
  6. 状态名称</td>
  7. <td>
  8. 排序号</td>
  9. </tr>
  10. <tr>
  11. <td>
  12. &nbsp;</td>
  13. <td>
  14. &nbsp;</td>
  15. <td>
  16. &nbsp;</td>
  17. </tr>
  18. </table>

调用示例如下代码:

  1. string refSQL = "select value,text,sortid from pub_chinaPay order by sortid";
  2. FillTable(tjTable, FillType.DynamicRows, true, 0, 1, 1);

输出结果如下图 

可以看到行为动态输出,标题列为预期的设置 。 

StaticRows 模式填充

静态填充,表示行、列均固定,由SQL查询结果根据预设输出,可设置每行每列的样式,如下图:

 前端代码示例 :

  1. <table id="tjTable" runat="server" align="center" border="1" style="width: 700px; border:1px solid #000000;border-collapse:collapse">
  2. <tr>
  3. <td>
  4. 状态代码</td>
  5. <td>
  6. 状态名称</td>
  7. <td>
  8. 排序号</td>
  9. </tr>
  10. <tr>
  11. <td>
  12. &nbsp;</td>
  13. <td>
  14. &nbsp;</td>
  15. <td>
  16. &nbsp;</td>
  17. </tr>
  18. <tr>
  19. <td>
  20. &nbsp;</td>
  21. <td>
  22. &nbsp;</td>
  23. <td>
  24. &nbsp;</td>
  25. </tr>
  26. <tr>
  27. <td>
  28. &nbsp;</td>
  29. <td>
  30. &nbsp;</td>
  31. <td>
  32. &nbsp;</td>
  33. </tr>
  34. <tr>
  35. <td>
  36. &nbsp;</td>
  37. <td>
  38. &nbsp;</td>
  39. <td>
  40. &nbsp;</td>
  41. </tr>
  42. <tr>
  43. <td>
  44. &nbsp;</td>
  45. <td>
  46. &nbsp;</td>
  47. <td>
  48. &nbsp;</td>
  49. </tr>
  50. <tr>
  51. <td>
  52. &nbsp;</td>
  53. <td>
  54. &nbsp;</td>
  55. <td>
  56. &nbsp;</td>
  57. </tr>
  58. <tr>
  59. <td>
  60. &nbsp;</td>
  61. <td>
  62. &nbsp;</td>
  63. <td>
  64. &nbsp;</td>
  65. </tr>
  66. <tr>
  67. <td>
  68. &nbsp;</td>
  69. <td>
  70. &nbsp;</td>
  71. <td>
  72. &nbsp;</td>
  73. </tr>
  74. </table>

调用示例如下代码:

  1. string refSQL = "select value,text,sortid from pub_chinaPay order by sortid";
  2. FillTable(tjTable,FillType.StaticRows, true, 0, 1, 1);

输出结果如下图 

可以看到行有冗余,因此静态行模式仅输出列和行的可见区域,即溢出和不足均不显示 。 

小结

关于 HtmlTable 的其它详细操作和介绍,可参照如下链接:

https://learn.microsoft.com/zh-cn/dotnet/api/system.web.ui.htmlcontrols.htmltable?view=netframework-4.8.1&redirectedfrom=MSDN

关于填充模式,是在实际的应用场景里进行输出 ,比如全动态适合于依赖SQL语句控制度较高的场景,而动态行则是比较常见的一种输出方式,静态行输出则比如我们提供一种填写表格,已经预设好最大行数,为体现整体统一的输出风格而应用。所以,我们可以根据自己的实际需要改造输出 的模式,本示例代码仅供您参考。 

感谢您的阅读,希望本文能够对您有所帮助。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/706277
推荐阅读
相关标签
  

闽ICP备14008679号