WPF中DocumentPaginator内图片无法显示的问题排查
WPF报表Logo图片不显示问题排查
问题描述
我在WPF中制作展示信息列表的报表,要求每页顶部带标题和Logo图片的页眉,内容超出自动分页。但预览时只能看到文本,同目录下的bmp格式Logo无法显示。我试过把图片加载逻辑移到GetPage函数外,传入BitmapImage给分页器类,还是没解决。
问题代码
public override DocumentPage GetPage(int pageNumber) { //Create a test string for the purposes of measurement. FormattedText text = GetFormattedText("A"); double col1_X = margin; double col2_X = col1_X + text.Width * 15; //Retreive the columns name string colName1 = dt.Columns[0].ColumnName; string colName2 = dt.Columns[1].ColumnName; //Calculate the range of rows that fits on this page int minRow = pageNumber * rowsPerPage; int maxRow = minRow + rowsPerPage; //Create the visual for the page DrawingVisual visual = new DrawingVisual(); //Set the position to the top-left corner of the principal area. Point point = new Point(margin, margin); using (DrawingContext dc = visual.RenderOpen()) { string Percorso = Environment.CurrentDirectory + "\\logo.bmp"; BitmapImage bitmap = new BitmapImage(new Uri(Percorso, UriKind.Relative)); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.Freeze(); //Draw the column header Typeface columnHeaderTypeface = new Typeface(typeface.FontFamily, FontStyles.Normal, FontWeights.Bold, FontStretches.Normal); point.X = margin; int contaColonne = 0; if (dt.Columns.Count > widths.Length) { throw new Exception("Numero di colonne diverso dal numero delle larghezze"); } foreach (DataColumn datacolumn in dt.Columns) { text = GetFormattedText(datacolumn.ColumnName, columnHeaderTypeface); dc.DrawText(text, point); point.X += widths[contaColonne]; contaColonne++; } //Draw header dc.DrawImage(bitmap, new Rect(100, 40, 60, 40)); Point HeaderPoint = new Point(200, 40); text = GetFormattedText("Resoconto pesate", 40, columnHeaderTypeface); dc.DrawText(text, HeaderPoint); HeaderPoint.X += 450; HeaderPoint.Y -= 30; text = GetFormattedText(DateTime.Today.ToShortDateString(), columnHeaderTypeface); dc.DrawText(text, HeaderPoint); //Draw footer text = GetFormattedText((pageNumber + 1).ToString(), columnHeaderTypeface); dc.DrawText(text, new Point((pageSize.Width - text.Width) / 2, PageSize.Height - (margin / 2) + text.Height / 2)); dc.DrawLine(new Pen(Brushes.Black, 2), new Point(margin, pageSize.Height - (margin / 2)), new Point(pageSize.Width - margin, pageSize.Height - (margin / 2))); //Draw the line underneath. dc.DrawLine(new Pen(Brushes.Black, 2), new Point(margin, margin + text.Height), new Point(pageSize.Width - margin, margin + text.Height)); point.Y += text.Height; //Draw the column values. for (int i = minRow; i < maxRow; i++) { //Check for the end of the last (half-filled) page. if (i > (dt.Rows.Count - 1)) break; point.X = margin; contaColonne = 0; foreach (DataColumn datacolumn in dt.Columns) { text = GetFormattedText(dt.Rows[i][datacolumn.ColumnName].ToString()); dc.DrawText(text, point); point.X += widths[contaColonne]; contaColonne++; } point.Y += text.Height; } dc.Close(); } return new DocumentPage(visual, pageSize, new Rect(pageSize), new Rect(pageSize)); }
问题原因及解决方案
1. 图片路径与Uri类型不匹配
你用Environment.CurrentDirectory + "\\logo.bmp"拼接绝对路径,却使用UriKind.Relative,会导致Uri解析错误。应改用绝对Uri加载:
string Percorso = Path.Combine(Environment.CurrentDirectory, "logo.bmp"); BitmapImage bitmap = new BitmapImage(new Uri(Percorso, UriKind.Absolute));
2. BitmapImage加载顺序错误
设置CacheOption = BitmapCacheOption.OnLoad的时机不对,必须在BeginInit和EndInit块内配置参数,确保加载逻辑生效:
BitmapImage bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.UriSource = new Uri(Percorso, UriKind.Absolute); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.EndInit(); bitmap.Freeze();
这种方式能避免异步加载导致的图片未就绪问题。
3. 图片绘制区域被覆盖
检查dc.DrawImage(bitmap, new Rect(100, 40, 60, 40))的位置:
- 确认该Rect未被后续绘制的列标题、文本覆盖;
- 可临时将Logo绘制到左上角(比如
new Rect(10,10,60,40))测试是否显示,排除位置问题。
4. 文件存在性与权限验证
- 用
File.Exists(Percorso)提前验证文件是否存在; - 确保程序有读取该文件的权限,尤其是部署后的环境。
5. 外部加载图片的正确方式
若要将图片加载移到GetPage外,需确保BitmapImage全局复用且冻结:
// 类级别全局变量 private BitmapImage _logoBitmap; // 构造函数或初始化方法中加载 public YourPaginatorClass() { string Percorso = Path.Combine(Environment.CurrentDirectory, "logo.bmp"); _logoBitmap = new BitmapImage(); _logoBitmap.BeginInit(); _logoBitmap.UriSource = new Uri(Percorso, UriKind.Absolute); _logoBitmap.CacheOption = BitmapCacheOption.OnLoad; _logoBitmap.EndInit(); _logoBitmap.Freeze(); // 冻结后支持跨线程使用,适配分页场景 } // 在GetPage中直接使用 dc.DrawImage(_logoBitmap, new Rect(100, 40, 60, 40));
内容的提问来源于stack exchange,提问作者Marco76
相关产品推荐
相关产品推荐

