When using PrintDialog.PrintDocument for printing in WPF, you need to prepare a FlowDocument for layout. FlowDocuments cannot be dispalyed directly in designers, so you typically design them in a UserControl or Window, then copy the XAML into the FlowDocument.
To populate the FlowDocument with data, pre-define named TextBlock eelments within the document. At runtime, iterate through your data source properties, locate the corresponding TextBlock by namme, and assign values accordingly.
1. FlowDocument Example
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FontFamily="SimSun">
<FlowDocument.Resources>
<Style x:Key="BorderLineStyle" TargetType="{x:Type Line}">
<Setter Property="Stroke" Value="Black"/>
<Setter Property="StrokeThickness" Value="1"/>
</Style>
</FlowDocument.Resources>
<Paragraph>
<Border>
<Canvas Name="PrintCanvas" Width="200" Height="100" Background="White">
<Line Style="{StaticResource BorderLineStyle}" X1="3" Y1="3" X2="194" Y2="3"/>
<Line Style="{StaticResource BorderLineStyle}" X1="194" Y1="3" X2="194" Y2="96"/>
<Line Style="{StaticResource BorderLineStyle}" X1="3" Y1="96" X2="194" Y2="96"/>
<Line Style="{StaticResource BorderLineStyle}" X1="3" Y1="3" X2="3" Y2="96"/>
<Grid Canvas.Left="5" Canvas.Top="5" Width="190" Height="90">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="123456有限公司"
TextAlignment="Center" FontSize="14"
HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock Text="商品批号:" FontSize="12" Margin="5,0,0,0"
HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<Line Style="{StaticResource BorderLineStyle}" X1="-5" Y1="21" X2="113" Y2="21"/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<TextBlock Text="物料编号 :" FontSize="12" Margin="5,0,0,0"
HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<Line Style="{StaticResource BorderLineStyle}" X1="-5" Y1="21" X2="113" Y2="21"/>
</StackPanel>
<StackPanel Grid.Row="3" Orientation="Horizontal">
<TextBlock Text="订 单 号 :" FontSize="12" Margin="5,0,0,0"
HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<Line Style="{StaticResource BorderLineStyle}" X1="-5" Y1="21" X2="113" Y2="21"/>
</StackPanel>
</Grid>
<TextBlock Name="BatchNumber" Canvas.Left="75" Canvas.Top="34" FontSize="12" Text="商品批号"/>
<TextBlock Name="MaterialNumber" Canvas.Left="75" Canvas.Top="56" FontSize="12" Text="物料编号"/>
<TextBlock Name="OrderNumber" Canvas.Left="75" Canvas.Top="78" FontSize="12" Text="订单号"/>
</Canvas>
</Border>
</Paragraph>
</FlowDocument>
2. Print Data Model
public class PrintDataModel
{
public string BatchNumber { get; set; }
public string OrderNumber { get; set; }
public string MaterialNumber { get; set; }
}
3. Document Renderer
public interface IDocumentFiller
{
void Fill(FlowDocument document, object data);
}
public class FlowDocumentFiller : IDocumentFiller
{
public void Fill(FlowDocument document, object data)
{
var printData = data as PrintDataModel;
if (printData == null)
{
throw new ArgumentException("Invalid data type. Expected PrintDataModel.");
}
var modelType = typeof(PrintDataModel);
var properties = modelType.GetProperties();
foreach (var prop in properties)
{
if (document.FindName(prop.Name) is TextBlock targetBlock)
{
var value = prop.GetValue(printData);
targetBlock.Text = value?.ToString() ?? string.Empty;
}
}
}
}
4. Printing Implementation
public void ExecutePrint(FlowDocument document, object data, string printerName, int copies)
{
var filler = new FlowDocumentFiller();
filler.Fill(document, data);
SendToPrinter(document, printerName, "Print Job", copies);
}
public static void SendToPrinter(FlowDocument document, string printerName, string jobDescription, int copies)
{
var printServer = new LocalPrintServer();
var queue = printServer.GetPrintQueue(printerName);
if (queue.IsInError)
{
throw new Exception("Printer is in error state.");
}
var dialog = new PrintDialog
{
PrintQueue = queue,
PrintTicket = { CopyCount = copies }
};
var width = (int)Math.Ceiling(dialog.PrintableAreaWidth);
var height = (int)Math.Ceiling(dialog.PrintableAreaHeight);
dialog.PrintTicket.PageMediaSize = new PageMediaSize(width, height);
var paper = GetPaperDimensions(printerName);
var marginX = (int)Math.Ceiling((paper.Width - width) / 2f);
var marginY = (int)Math.Ceiling((paper.Height - height) / 2f);
document.PagePadding = new Thickness(marginX, marginY, marginX, marginY);
var paginator = ((IDocumentPaginatorSource)document).DocumentPaginator;
dialog.PrintDocument(paginator, jobDescription);
}