如何从SQL Server 2008 R2检索数据并实现WinForms行转列展示
实现WinForms中自定义格式的数据展示
这个需求其实很好实现,核心就是把数据库里的扁平单条记录,拆分成WinForms界面上的多行状态项展示。我给你两种实用方案,你可以根据状态数量是否固定来选择:
方案一:固定布局(状态数量确定时用)
如果你的状态项(Report Status、Inspection Status等)数量是固定不变的,直接在设计器里拖控件布局最省心:
在Form设计器里搭建界面
按照你要的格式,拖入多组Label:- 第一组:左边Label显示
(PK)Job Number,右边Label留空用于绑定工号 - 第二组:左边Label显示
Report Status(设置下划线,后面说方法),右边Label留空显示状态值 | ECD - 第三组:左边Label显示
Inspection Status,右边Label显示对应内容 - 后续状态项以此类推
- 第一组:左边Label显示
设置下划线效果
要实现你要的长下划线,有两种方式:- 简单版:选中左边的状态名称Label,在属性面板里把
Font设置为下划线样式 - 进阶版(长下划线铺满宽度):给Label添加
Paint事件,手动绘制下划线:private void lblStatusLabel_Paint(object sender, PaintEventArgs e) { var lbl = sender as Label; if (lbl == null) return; // 在Label底部绘制一条黑色下划线,距离底部2像素 e.Graphics.DrawLine(Pens.Black, 0, lbl.Height - 2, lbl.Width, lbl.Height - 2); }
- 简单版:选中左边的状态名称Label,在属性面板里把
从数据库读取并赋值
拿到数据库的记录后,直接给对应的Label赋值:// 假设dr是从数据库读取的DataRow lblJobNumberValue.Text = dr["Jobnumber"].ToString(); // 格式化Report Status和ECD lblReportStatusValue.Text = $"{dr["ReportStatus"]} | {Convert.ToDateTime(dr["ReportECD"]):yyyy-MM-dd}"; // 格式化Inspection Status和ECD lblInspectionStatusValue.Text = $"{dr["InspectionStatus"]} | {Convert.ToDateTime(dr["InspectionECD"]):yyyy-MM-dd}"; // 其他状态项同理
方案二:动态布局(状态数量不固定时用)
如果状态项可能随时增减,用TableLayoutPanel动态生成行更灵活:
定义数据模型
先把数据库的扁平数据转换成更易处理的实体类,方便后续遍历:// 单个状态项的模型 public class JobStatusItem { public string StatusName { get; set; } // 比如"Report Status" public string StatusValue { get; set; } // 状态值,比如"Completed" public DateTime ECD { get; set; } // 对应的ECD日期 } // 整条工单的模型 public class JobRecord { public string JobNumber { get; set; } public List<JobStatusItem> StatusItems { get; set; } = new List<JobStatusItem>(); }把数据库记录转成模型
从数据库读取数据后,映射成JobRecord对象:// 假设dr是数据库返回的DataRow var jobRecord = new JobRecord { JobNumber = dr["Jobnumber"].ToString() }; // 添加各个状态项,注意对应数据库里的字段名 jobRecord.StatusItems.Add(new JobStatusItem { StatusName = "Report Status", StatusValue = dr["ReportStatus"].ToString(), ECD = Convert.ToDateTime(dr["ReportECD"]) }); jobRecord.StatusItems.Add(new JobStatusItem { StatusName = "Inspection Status", StatusValue = dr["InspectionStatus"].ToString(), ECD = Convert.ToDateTime(dr["InspectionECD"]) }); jobRecord.StatusItems.Add(new JobStatusItem { StatusName = "Qual. Status", StatusValue = dr["QualificationStatus"].ToString(), ECD = Convert.ToDateTime(dr["QualificationECD"]) });动态生成界面控件
在Form里拖入一个TableLayoutPanel(命名为tlpJobDetails),设置ColumnCount为2,然后用代码动态添加行:// 先添加Job Number行 var lblJobLabel = new Label { Text = "(PK)Job Number", AutoSize = true }; var lblJobValue = new Label { Text = jobRecord.JobNumber, AutoSize = true, Dock = DockStyle.Fill }; tlpJobDetails.RowStyles.Add(new RowStyle(SizeType.AutoSize)); tlpJobDetails.Controls.Add(lblJobLabel, 0, tlpJobDetails.RowCount - 1); tlpJobDetails.Controls.Add(lblJobValue, 1, tlpJobDetails.RowCount - 1); // 遍历状态项,添加每一行 foreach (var statusItem in jobRecord.StatusItems) { // 左边的状态名称Label(带长下划线) var lblStatusName = new Label { Text = statusItem.StatusName, AutoSize = true, Padding = new Padding(0, 0, 0, 2) }; // 给Label添加Paint事件绘制下划线 lblStatusName.Paint += (s, e) => { var lbl = s as Label; if (lbl != null) e.Graphics.DrawLine(Pens.Black, 0, lbl.Height - 2, lbl.Width, lbl.Height - 2); }; // 右边的状态值+ECD var lblStatusECD = new Label { Text = $"{statusItem.StatusValue} | {statusItem.ECD:yyyy-MM-dd}", AutoSize = true, Dock = DockStyle.Fill, TextAlign = ContentAlignment.MiddleLeft }; // 添加到TableLayoutPanel tlpJobDetails.RowStyles.Add(new RowStyle(SizeType.AutoSize)); int rowIndex = tlpJobDetails.RowCount - 1; tlpJobDetails.Controls.Add(lblStatusName, 0, rowIndex); tlpJobDetails.Controls.Add(lblStatusECD, 1, rowIndex); }
两种方案都能完美实现你要的展示效果,固定布局适合简单场景,动态布局更灵活适配变化。
内容的提问来源于stack exchange,提问作者JDesigns
相关产品推荐
相关产品推荐

