Xamarin Forms跨端如何基于下单逻辑实现订单PDF生成的CreatePdfFile函数
Xamarin.Forms订单PDF生成功能实现方案
步骤1:安装适配双端的PDF生成依赖
给共享项目、Android项目、iOS项目分别安装NuGet包QuestPDF:
- 若项目为.NET Standard 2.0的老版本Xamarin.Forms,选择安装2022.12.*版本的QuestPDF
- 若项目为.NET 6+的升级版本,直接安装最新版即可
- iOS端额外需在Info.plist中添加系统字体访问权限,避免渲染异常
步骤2:实现CreatePdfFile函数
该函数直接复用PlaceOrderAsync中已获取的订单、用户、购物车数据,无需重复查库:
using QuestPDF.Fluent; using QuestPDF.Helpers; using QuestPDF.Infrastructure; using Xamarin.Essentials; public async Task<string> CreatePdfFile(string orderId, string userName, List<CartItem> cartItems) { // 生成PDF存储路径,默认存在应用私有缓存目录,无需申请额外权限 var pdfPath = Path.Combine(FileSystem.CacheDirectory, $"订单_{orderId}.pdf"); // 构建PDF内容结构 Document.Create(container => { container.Page(page => { page.Size(PageSizes.A4); page.Margin(2, Unit.Centimetre); page.DefaultTextStyle(x => x.FontSize(12)); // 页眉 page.Header() .Text($"订单编号:{orderId}") .SemiBold().FontSize(20).FontColor(Colors.Blue.Medium); // 正文区域 page.Content() .Column(column => { column.Spacing(10); column.Item().Text($"下单用户:{userName}"); column.Item().Text($"下单时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"); column.Item().Text("商品清单:").SemiBold(); // 商品列表表格 column.Item().Table(table => { table.BorderCollapse = true; table.Border(1); table.ColumnsDefinition(columns => { columns.ConstantColumn(120); columns.AutoColumn(); }); // 表头 table.Cell().Border(1).Padding(5).Text("商品ID").SemiBold(); table.Cell().Border(1).Padding(5).Text("商品名称").SemiBold(); // 填充商品数据 foreach (var item in cartItems) { table.Cell().Border(1).Padding(5).Text(item.ProductId); table.Cell().Border(1).Padding(5).Text(item.ProductName); } }); }); // 页脚 page.Footer() .AlignCenter() .Text(x => { x.Span("第 "); x.CurrentPageNumber(); x.Span(" 页 / 共 "); x.TotalPages(); x.Span(" 页"); }); }); }) .GeneratePdf(pdfPath); return pdfPath; }
步骤3:改造现有PlaceOrderAsync方法,集成PDF生成逻辑
public async Task<string> PlaceOrderAsync() { var cn = DependencyService.Get<ISQLite>().GetConnection(); var data = cn.Table<CartItem>().ToList(); var orderId = Guid.NewGuid().ToString(); var uname = Preferences.Get("Username", "Guest"); foreach(var item in data) { OrderDetails od = new OrderDetails() { OrderId = orderId, OrderDetailId = Guid.NewGuid().ToString(), ProductId = item.ProductId, ProductName = item.ProductName }; await client.Child("OrderDetails").PostAsync(od); } await client.Child("Orders").PostAsync( new Order() { OrderId = orderId, Username = uname }); // 新增PDF生成+打开逻辑 var pdfFilePath = await CreatePdfFile(orderId, uname, data); // 如需生成后直接打开PDF,启用下方代码 // await Launcher.OpenAsync(new OpenFileRequest // { // File = new ReadOnlyFile(pdfFilePath) // }); return orderId; }
注意事项
- Android 13及以上版本如果需要把PDF导出到公共存储目录,需要在AndroidManifest.xml中添加
READ_MEDIA_IMAGES、WRITE_EXTERNAL_STORAGE对应权限,存储在应用私有目录无需申请权限 - iOS端如果出现字体渲染异常,可以在生成PDF时手动指定iOS内置的Helvetica字体
- 如需自定义PDF的样式、增加商品价格、总价等字段,直接修改CreatePdfFile中的内容结构即可
内容的提问来源于stack exchange,提问作者user14663436
相关产品推荐
相关产品推荐

