VB.NET中DataGridView表头预览可见但打印消失问题求助
解决VB.NET PrintDocument打印DataGridView表头预览可见但实际打印消失的问题
问题根源
你的代码存在三个核心问题:
- 未在打印开始时重置
mRow和newPage的状态,导致实际打印时newPage可能未被设为True,第一页表头无法绘制; - 未处理多页打印的状态传递,后续页面不会触发表头绘制;
- 打印单元格内容时修改了全局的
StringFormat对齐方式,会影响表头的居中绘制效果。
修复方案
1. 声明类级变量
确保mRow和newPage是窗体/类的成员变量(不是局部变量):
Private mRow As Integer = 0 Private newPage As Boolean = True
2. 添加BeginPrint事件处理
在打印开始时重置状态,保证每次打印/预览都从头开始,第一页会绘制表头:
Private Sub PrintDocument1_BeginPrint(sender As Object, e As Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint mRow = 0 newPage = True End Sub
3. 修改PrintPage事件代码
修复多页逻辑、避免StringFormat污染:
Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage Dim format As New StringFormat format.Alignment = StringAlignment.Center e.Graphics.DrawString("PULL OUT", New Font("Century Gothic", 25, FontStyle.Bold), Brushes.Black, New Point(400, 20), format) ' 用于表头的StringFormat,保持居中 Dim headerFmt As New StringFormat(StringFormatFlags.LineLimit) headerFmt.LineAlignment = StringAlignment.Center headerFmt.Trimming = StringTrimming.EllipsisCharacter headerFmt.Alignment = StringAlignment.Center ' 用于单元格内容的StringFormat,单独创建避免污染表头格式 Dim cellFmt As New StringFormat(StringFormatFlags.LineLimit) cellFmt.LineAlignment = StringAlignment.Center cellFmt.Trimming = StringTrimming.EllipsisCharacter cellFmt.Alignment = StringAlignment.Near Dim y As Integer = 100 Dim x As Integer = 100 Dim h As Integer = 0 Dim rc As Rectangle Dim row As DataGridViewRow ' 绘制表头 If newPage Then ' 使用列集合直接绘制表头,逻辑更清晰 For Each col As DataGridViewColumn In DataGridView1.Columns If col.Visible Then rc = New Rectangle(x, y, col.Width, DataGridView1.ColumnHeadersHeight) e.Graphics.FillRectangle(Brushes.LightGray, rc) e.Graphics.DrawRectangle(Pens.Black, rc) e.Graphics.DrawString(col.HeaderText, DataGridView1.Font, Brushes.Black, rc, headerFmt) x += rc.Width h = Math.Max(h, rc.Height) End If Next y += h End If newPage = False Dim displayNow As Integer For displayNow = mRow To DataGridView1.RowCount - 1 row = DataGridView1.Rows(displayNow) x = 100 h = 0 ' 绘制行内容 For Each cell As DataGridViewCell In row.Cells If cell.Visible Then rc = New Rectangle(x, y, cell.Size.Width, cell.Size.Height) e.Graphics.DrawRectangle(Pens.Black, rc) ' 使用单独的cellFmt,不修改表头的格式 rc.Offset(10, 0) e.Graphics.DrawString(cell.FormattedValue.ToString, DataGridView1.Font, Brushes.Black, rc, cellFmt) x += rc.Width h = Math.Max(h, rc.Height) End If Next y += h ' 判断是否超出页面边界,准备下一页 If y + h > e.MarginBounds.Bottom Then mRow = displayNow + 1 newPage = True e.HasMorePages = True Return End If Next ' 所有行打印完成,重置状态 e.HasMorePages = False mRow = 0 newPage = True End Sub
关键修改说明
- 分离StringFormat:表头和单元格内容使用各自的
StringFormat,避免修改对齐方式后互相影响; - BeginPrint初始化:每次打印开始时重置
mRow和newPage,确保第一页一定会绘制表头; - 多页判断:在打印每行后检查是否超出页边距,设置
e.HasMorePages = True并更新状态,让下一页自动触发表头绘制; - 表头绘制优化:直接遍历
DataGridView.Columns获取表头文本和宽度,不需要依赖行单元格,逻辑更稳定。
内容的提问来源于stack exchange,提问作者Koweenss
相关产品推荐
相关产品推荐

