如何为DataGrid单元格设置InnerHtml并保留文本框解决Chrome打印空白问题?
解决Chrome打印时DataGrid文本框不显示的问题
这个问题本质是Chrome的默认打印样式对表单控件(比如<input>)的渲染逻辑导致的——默认情况下,Chrome可能会隐藏表单元素或者给它们加上不符合预期的样式,使得打印时看起来空白;而纯文本则能被正常渲染。下面给你几个可行的解决方案,按实现复杂度从低到高排序:
方案1:添加打印专用CSS(最推荐)
只需要在页面的样式中添加打印媒体查询,让文本框在打印时显示为纯文本样式,既保留编辑功能,又能正常打印内容:
@media print { /* 针对DataGrid里的文本框调整打印样式 */ input[type="text"] { border: none; /* 去掉边框 */ background: transparent; /* 去掉背景 */ -webkit-appearance: none; /* 移除Chrome默认的表单控件样式 */ appearance: none; width: auto; /* 让宽度适配内容 */ vertical-align: middle; /* 和单元格内容对齐 */ color: inherit; /* 继承文本颜色 */ font: inherit; /* 继承字体样式 */ } }
这个方案不需要修改后台代码,只加一段CSS就能解决问题,打印时文本框会以纯文本的样式显示内容,同时页面上仍然是可编辑的文本框。
方案2:双内容模式(屏幕显示文本框,打印显示纯文本)
如果方案1不生效,可以给单元格同时添加可编辑的文本框和用于打印的隐藏文本,通过CSS控制不同场景下的显示:
第一步:修改后台代码,生成双内容结构
把你原来的c.Text赋值代码改成这样(用字符串插值让代码更清晰):
var id = ((DataRowView)e.Item.DataItem).Row["ID"].ToString(); var buyValue = ((DataRowView)e.Item.DataItem).Row["Buy0_45"].ToString(); // 同时添加打印用的隐藏span和可编辑的input c.Text = $"<span class=\"print-content\">{buyValue}</span>" + $"<input id=\"txtBuy0-45{id}\" style=\"width:50px\" type=\"text\" value=\"{buyValue}\" onblur=\"UpdateBuyRate('0',{id},this.value)\" />";
第二步:添加控制显示的CSS
/* 屏幕上隐藏打印内容,显示文本框 */ .print-content { display: none; } /* 打印时隐藏文本框,显示纯文本 */ @media print { .print-content { display: inline; } input[type="text"] { display: none; } }
第三步:同步编辑后的内容到打印文本
因为用户编辑文本框后,打印内容需要同步更新,所以修改你的UpdateBuyRate函数:
function UpdateBuyRate(param1, id, value) { // 原来的更新逻辑(比如提交到后台) // ... // 同步更新打印用的span内容 const printSpan = document.querySelector(`#txtBuy0-45${id}`).previousElementSibling; if (printSpan) { printSpan.textContent = value; } }
方案3:打印前后临时替换内容
通过监听浏览器的打印事件,在打印前把文本框替换成纯文本,打印完成后再恢复文本框:
第一步:后台代码给单元格添加标记
修改后台代码,给包含文本框的单元格添加自定义属性,方便后续JS识别和恢复:
var id = ((DataRowView)e.Item.DataItem).Row["ID"].ToString(); var buyValue = ((DataRowView)e.Item.DataItem).Row["Buy0_45"].ToString(); var inputHtml = $"<input id=\"txtBuy0-45{id}\" style=\"width:50px\" type=\"text\" value=\"{buyValue}\" onblur=\"UpdateBuyRate('0',{id},this.value)\" />"; c.Text = inputHtml; // 添加标记,说明这个单元格有文本框 c.Attributes["data-is-editable-cell"] = "true"; // 保存原始的input HTML,用于恢复 c.Attributes["data-original-html"] = inputHtml;
第二步:添加打印事件监听的JS
// 打印前替换文本框为纯文本 window.addEventListener('beforeprint', function() { document.querySelectorAll('td[data-is-editable-cell="true"]').forEach(cell => { const input = cell.querySelector('input'); if (input) { // 保存当前输入的值 cell.dataset.currentValue = input.value; // 替换为纯文本 cell.textContent = input.value; } }); }); // 打印后恢复文本框 window.addEventListener('afterprint', function() { document.querySelectorAll('td[data-is-editable-cell="true"]').forEach(cell => { const originalHtml = cell.dataset.originalHtml; const currentValue = cell.dataset.currentValue; // 恢复原始HTML cell.innerHTML = originalHtml; // 把当前值回填到文本框 const input = cell.querySelector('input'); if (input && currentValue) { input.value = currentValue; } }); });
以上三个方案中,方案1最简洁高效,建议优先尝试;如果因为特殊样式需求方案1不适用,再考虑方案2或3。
内容的提问来源于stack exchange,提问作者user123456789
相关产品推荐
相关产品推荐

