WPF的打印预览+⽤户⾃定义PDF模板的编写(HTMLtoPDF)
模板编写
模板准备使⽤Antlr3.StringTemplate+HtmlRenderer来实现。
接下来实现的是⼀个下⾯⼀个RichTextBox来编辑模板,上⾯⼀个HtmlRenderer的HtmlPanel控件来显⽰模板编辑后的HTML的样式,且每秒刷新⼀次,然后左边使⽤固定的包含属性的TreeView,能够将属性格式直接拖到RichTextBox中,⽅便后台对数据的填充
编辑模板界⾯
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TreeView x:Name="treeview" Grid.Column="0" PreviewMouseLeftButtonDown="TreeView_MouseDown"></TreeView>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" Width="4" Background="#BFDBFF" />
<Grid  Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="80" />
<RowDefinition Height="auto" />
<RowDefinition Height="150" MinHeight="50" />
</Grid.RowDefinitions>
<wpf1:HtmlPanel x:Name="_htmlPanel" Grid.Row="0">
<wpf1:HtmlPanel.ToolTip>
<ToolTip BorderBrush="Transparent" Padding="0">
<wpf1:HtmlLabel x:Name="_htmlTooltipLabel"/>
</ToolTip>
</wpf1:HtmlPanel.ToolTip>
</wpf1:HtmlPanel>
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" Height="4" Background="#BFDBFF" />
<xctk:RichTextBox x:Name="_htmlEditor" Grid.Row="2" VerticalScrollBarVisibility="Visible" BorderThickness="0"
TextChanged="OnHtmlEditor_TextChanged" AllowDrop="True" PreviewDrop="_htmlEditor_Drop"/>
</Grid>
</Grid>
public partial class SetHtmlWindow : Window
{
private bool _updateLock;
private readonly Timer _updateHtmlTimer;
private Dictionary<string, string> _dic = new Dictionary<string, string>() {
{"$标题$","$Title$" },
{"$头$","$Head$" },
{"$⾝体$","$Body$" },
};
public SetHtmlWindow()
{
InitializeComponent();
_updateHtmlTimer = new Timer(OnUpdateHtmlTimerTick);
treeview.ItemsSource = _dic.Keys;
}
public SetHtmlWindow(Dictionary<string, string> dic) : this()
{
this._dic = dic;
}
/// <summary>
/// On text change in the html editor update
/// </summary>
private void OnHtmlEditor_TextChanged(object sender, TextChangedEventArgs e)
{
if (!_updateLock)
{
{
_updateHtmlTimer.Change(1000, int.MaxValue);
}
}
/// <summary>
/// Set html syntax color text on the RTF html editor.
/// </summary>
private void SetColoredText(string text, bool color)
{
var selectionStart = _htmlEditor.CaretPosition;
_htmlEditor.Text = color ? HtmlSyntaxHighlighter.Process(text) : text.Replace("\n", "\\par ");
_htmlEditor.CaretPosition = selectionStart;
}
/// <summary>
/// Get the html text from the html editor control.
/// </summary>
private string GetHtmlEditorText()
{
return new TextRange(_htmlEditor.Document.ContentStart, _htmlEditor.Document.ContentEnd).Text;
}
/// <summary>
/// Update the html renderer with text from html editor.
/// </summary>
private void OnUpdateHtmlTimerTick(object state)
{
Dispatcher.BeginInvoke(new Action<Object>(o =>
{
_updateLock = true;
try
{
_htmlPanel.Text = GetHtmlEditorText();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Failed to render HTML");
}
_updateLock = false;
}), state);
}
private void TreeView_MouseDown(object sender, MouseButtonEventArgs e)
{
var treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;        string key = treeViewItem.DataContext.ToString();
DragDrop.DoDragDrop(treeViewItem, key, DragDropEffects.Copy);
}
static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
while (source != null && source.GetType() != typeof(T))
source = VisualTreeHelper.GetParent(source);
return source;
}
private void _htmlEditor_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(string)))
{
string result = e.Data.GetData(typeof(string)) as string;
string value = _dic[result];
e.Data.SetData(value);
}
}
private void SaveBtn_Click(object sender, RoutedEventArgs e)
{
if (MessageBoxHelper.ShowMessage("The file will be overwritten. Are you sure you want to save it?", "⽂件将被覆盖,是否确定保存?", (LangType)Sy sInfoModel.SysInfo.LangType, true))
{
var templatePath = @"templates\page.st";
File.WriteAllText(templatePath, GetHtmlEditorText());
}
}
private void CancleBtn_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
string page = new ReportPage().Generate();
_htmlEditor.Document.Blocks.Clear();
_htmlEditor.Document.Blocks.Add(new Paragraph(new Run(page)));
_htmlPanel.Text = page;
SetColoredText(GetHtmlEditorText(), true);
}
}
public abstract class Page
{
/** My template library */
protected static StringTemplateGroup templates =
html document是什么
new StringTemplateGroup("mygroup", "templates");
public string Generate()
{
var templatePath = @"templates\page.st";
string page = File.ReadAllText(templatePath);
return page;
}
public string Generate(Dictionary<string, string> Dic)
{
templates.FileCharEncoding = Encoding.UTF8;
StringTemplate pageST = templates.GetInstanceOf("page");
GenerateBody(pageST, Dic);
string page = pageST.ToString(); // render page
return page;
}
public abstract void GenerateBody(StringTemplate stringTemplate, Dictionary<string, string> Dic);
protected string Set(string str)
{
if (string.IsNullOrEmpty(str))
return " ";
return str;
}
}
public class ReportPage : Page
{
/** This "controller" pulls from "model" and pushes to "view" */
public override void GenerateBody(StringTemplate stringTemplateDictionary<string,string> Dic)
{
stringTemplate.SetAttribute("Title", Set(Dic["Title"]));
stringTemplate.SetAttribute("Head", Set(Dic["Head"]));
stringTemplate.SetAttribute("Body", Set(Dic["Body"]));
}
}
}
打印预览
模板编辑好了之后从Nuget添加FreeSpire.PDF,它能⽀持10页之内的PDF⽂件操作免费
然后后⾯是打印预览界⾯
void Show()
{
string page = GetHTML();
string tempXpsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Helper","temp.xps");
SpireToXPS(page, tempXpsPath);
var xpsd = new XpsDocument(tempXpsPath, FileAccess.Read);
docViewer.Document = xpsd.GetFixedDocumentSequence();
xpsd.Close();
}
private string GetHTML()
{
Dictionary<string, string> Dic = new Dictionary<string, string>();
Dic.Add("Title", "我的⼤标题");
Dic.Add("Head", “我的⼤头”);
Dic.Add("Body", “我的肚⽪”);
string page = new Windows.ReportPage().Generate(Dic);
return page;
}
private void SpireToXPS(string htmlCode, string outputPath = "output.xps")
{
Spire.Pdf.PdfDocument doc = new Spire.Pdf.PdfDocument();
Spire.Pdf.HtmlConverter.PdfHtmlLayoutFormat htmlLayoutFormat = new Spire.Pdf.HtmlConverter.PdfHtmlLayoutFormat();    htmlLayoutFormat.IsWaiting = false;
htmlLayoutFormat.FitToHtml = Spire.Pdf.HtmlConverter.Clip.Both;
Spire.Pdf.PdfPageSettings setting = new Spire.Pdf.PdfPageSettings();
setting.Margins = new Spire.Pdf.Graphics.PdfMargins(50);
setting.Size = Spire.Pdf.PdfPageSize.A4;
Thread thread = new Thread(() =>
{
doc.LoadFromHTML(htmlCode, false, setting, htmlLayoutFormat, true);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
doc.SaveToFile(outputPath, Spire.Pdf.FileFormat.XPS);
doc.Close();
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。