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

2024-06-06 14:04

本文主要是介绍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 语句:

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

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

insert into pub_ChinaPay(value,text,sortid) values('****','默认状态',1)
insert into pub_ChinaPay(value,text,sortid) values('    ','待支付',2)
insert into pub_ChinaPay(value,text,sortid) values('1001','消费交易成功',3)
insert into pub_ChinaPay(value,text,sortid) values('1003','退款提交成功',4)
insert into pub_ChinaPay(value,text,sortid) values('1005','退款撤销成功',5)
insert into pub_ChinaPay(value,text,sortid) values('0003','交易失败',6)
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 方法实现代码如下:

int RowsCount = 0;
int ErrorNum = 0;
string ErrorMessage = "";public object[,] GetReaderData(string DbServerType,string strConn,string _sql,ArrayList paras,bool hastitle,CommandType ct)
{if((DbServerType.ToLower()=="")||(DbServerType.ToLower()=="sqlserver")){SqlConnection Conn = new SqlConnection(strConn );SqlCommand Cmd = new SqlCommand();Cmd.CommandType=ct;Cmd.Connection = Conn;SqlDataReader myDr;Cmd.CommandText =_sql;if(paras!=null){for(int i=0;i<paras.Count;i++){Cmd.Parameters.Add((SqlParameter)paras[i]);}}try{Conn.Open();myDr = Cmd.ExecuteReader();ArrayList rowdata = new ArrayList();int _fieldcount=myDr.FieldCount;Object[] colvalues = new Object[_fieldcount];for(int i=0;i<_fieldcount;i++){colvalues[i]=myDr.GetName(i);}if(hastitle)rowdata.Add(colvalues);while(myDr.Read()){Object[] values = new Object[_fieldcount];myDr.GetValues(values);rowdata.Add(values);RowsCount++;}myDr.Close();object[,] rv=new object[rowdata.Count,_fieldcount];for(int i=0;i<rowdata.Count;i++){for(int j=0;j<_fieldcount;j++){rv[i,j]=((object[])rowdata[i])[j];}}return rv;}catch (SqlException e){ErrorMessage=e.Message;return null;}finally{Conn.Close();Conn.Dispose();}}//sqlserverif(DbServerType.ToLower()=="oracle"){OracleConnection Conn = new OracleConnection(strConn );OracleCommand Cmd = new OracleCommand();Cmd.Connection = Conn;OracleDataReader myDr;Cmd.CommandText =_sql;if(paras!=null){for(int i=0;i<paras.Count;i++){Cmd.Parameters.Add((OracleParameter)paras[i]);}}try{Conn.Open();myDr = Cmd.ExecuteReader();ArrayList rowdata = new ArrayList();int _fieldcount=myDr.FieldCount;Object[] colvalues = new Object[_fieldcount];for(int i=0;i<_fieldcount;i++){colvalues[i]=myDr.GetName(i);}if(hastitle)rowdata.Add(colvalues);while(myDr.Read()){Object[] values = new Object[_fieldcount];myDr.GetValues(values);rowdata.Add(values);RowsCount++;}myDr.Close();object[,] rv=new object[rowdata.Count,_fieldcount];for(int i=0;i<rowdata.Count;i++){for(int j=0;j<_fieldcount;j++){rv[i,j]=((object[])rowdata[i])[j];}}return rv;}catch (OracleException e){ErrorMessage=e.Message;return null;}finally{Conn.Close();Conn.Dispose();}}//oracleif (DbServerType.ToLower() == "dm8"){DmConnection Conn = new DmConnection(strConn);DmCommand Cmd = new DmCommand();Cmd.CommandType = ct;Cmd.Connection = Conn;DmDataReader myDr;Cmd.CommandText = _sql;if (paras != null){for (int i = 0; i < paras.Count; i++){Cmd.Parameters.Add((DmParameter)paras[i]);}}try{Conn.Open();myDr = Cmd.ExecuteReader() as DmDataReader;ArrayList rowdata = new ArrayList();int _fieldcount = myDr.FieldCount;Object[] colvalues = new Object[_fieldcount];for (int i = 0; i < _fieldcount; i++){colvalues[i] = myDr.GetName(i);}if (hastitle)rowdata.Add(colvalues);while (myDr.Read()){Object[] values = new Object[_fieldcount];myDr.GetValues(values);rowdata.Add(values);RowsCount++;}myDr.Close();object[,] rv = new object[rowdata.Count, _fieldcount];for (int i = 0; i < rowdata.Count; i++){for (int j = 0; j < _fieldcount; j++){rv[i, j] = ((object[])rowdata[i])[j];}}return rv;}catch (DmException e){ErrorMessage = e.Message;return null;}finally{Conn.Close();Conn.Dispose();}}//dm8return null;
}//getreaddata

FillTable 方法实现代码如下:

ArrayList paras=new ArrayList();
string refSql="";
bool hastitle=false;
System.Data.CommandType ct=System.Data.CommandType.Text;
public void FillTable(HtmlTable tb, FillType ft, bool SpaceInEmptyCell, int MinClearRowsCount, int refStartRowId,int refCopyRowId,bool allowToHTML){object[,] ReaderData = GetReaderData("SqlServer","您的连接串","",paras,hastitle,ct);if (ReaderData == null && RowsCount==0){while (tb.Rows.Count > MinClearRowsCount){tb.Rows.RemoveAt(tb.Rows.Count - 1);}return;}if (ft == FillType.Automatic || ft==FillType.DynamicRows || ft==FillType.StaticRows){if (ft == FillType.Automatic){int addcells = ReaderData.GetLength(1) - tb.Rows[0].Cells.Count;for (int i = 0; i < tb.Rows.Count; i++){for (int j = 0; j < addcells; j++){HtmlTableCell tc = new HtmlTableCell();if (allowToHTML == true){tc.Attributes.Add("ByHTML", "true");}tb.Rows[i].Cells.Add(tc);}}if (tb.Rows.Count == 2){for (int j = 0; j < ReaderData.GetLength(1); j++){string _fieldname = ReaderData[0, j].ToString();tb.Rows[0].Cells[j].InnerText = _fieldname;}}}int startRowID = tb.Rows.Count - 1;int copyRowID = 0;if (ft == FillType.StaticRows){if (HasTitle == true){startRowID = tb.Rows.Count > 1 ? 1 : 0;}else{startRowID = 0;}}if (refStartRowId != -1) startRowID = refStartRowId;if (refCopyRowId != -1) copyRowID = refCopyRowId;for (int i = (HasTitle == true ? 1 : 0); i < ReaderData.GetLength(0); i++){if (startRowID>tb.Rows.Count-1) break;for (int j = 0; j < ReaderData.GetLength(1); j++){if (j > tb.Rows[copyRowID].Cells.Count - 1) break;HtmlTableCell td = tb.Rows[startRowID].Cells[j];if (td.Attributes["ByHTML"] == null){td.InnerText = ReaderData[i, j].ToString();}else{td.InnerHtml = allowToHTML == true ? (ReaderData[i, j].ToString()) : ReaderData[i, j].ToString();;}if (td.InnerText == "" && SpaceInEmptyCell == true) td.InnerHtml="&nbsp;";}if (i == ReaderData.GetLength(0)-1) break;if (ft == FillType.Automatic || ft == FillType.DynamicRows){HtmlTableRow tr = new HtmlTableRow();tb.Rows.Add(tr);for (int k = 0; k < tb.Rows[copyRowID].Cells.Count; k++){HtmlTableCell prv_tc = tb.Rows[startRowID].Cells[k];HtmlTableCell tc = new HtmlTableCell();tr.Cells.Add(tc);CloneStyles(prv_tc, tc);}}startRowID ++;}}
}//fill table
void CloneStyles(HtmlControl obj, HtmlControl newobj)
{IEnumerator keys = obj.Style.Keys.GetEnumerator();while (keys.MoveNext()){String key = (String)keys.Current; newobj.Style[key] = obj.Style[key];}IEnumerator keys2 = obj.Attributes.Keys.GetEnumerator();while (keys2.MoveNext()){String key = (String)keys2.Current; newobj.Attributes[key] = obj.Attributes[key];}}

模板样例输出

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

Automatic 模式填充

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

 前端代码示例 :

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

调用示例如下代码:

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

输出结果如下图 

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

DynamicRows 模式填充

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

 前端代码示例 :

<table id="tjTable" runat="server" align="center" border="1" style="width: 700px; border:1px solid #000000;border-collapse:collapse"><tr><td>状态代码</td><td>状态名称</td><td>排序号</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr></table>

调用示例如下代码:

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

输出结果如下图 

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

StaticRows 模式填充

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

 前端代码示例 :

<table id="tjTable" runat="server" align="center" border="1" style="width: 700px; border:1px solid #000000;border-collapse:collapse"><tr><td>状态代码</td><td>状态名称</td><td>排序号</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr></table>

调用示例如下代码:

string refSQL = "select value,text,sortid from pub_chinaPay order by sortid";
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语句控制度较高的场景,而动态行则是比较常见的一种输出方式,静态行输出则比如我们提供一种填写表格,已经预设好最大行数,为体现整体统一的输出风格而应用。所以,我们可以根据自己的实际需要改造输出 的模式,本示例代码仅供您参考。 

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

这篇关于C# Web控件与数据感应之 填充 HtmlTable的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036312

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06