基于Silverlight打印的使用详解,是否为微软的Bug问题
1:新建Silverlight4 应用程序,名称为SLStudy。建好后如下:
2:在SLStudy下新建Silverlight用户控件,Print1.xaml作为要打印的控件。
在Print1.xaml里面添加代码为:
<Grid x:Name="LayoutRoot" Background="White">
<Button>这是第一个例子,简单的按钮</Button>
</Grid>
3:已经建立好了要打印的内容了,这里打印的是一个按钮。
4:修改MainPage.xaml代码如下:
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<Button x:Name="btnPrint1" Click="btnPrint1_Click">Print1</Button>
</StackPanel>
</Grid>
5:后台代码为:
private void btnPrint1_Click(object sender, RoutedEventArgs e)
{
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += new EventHandler<PrintPageEventArgs>(printDocument_PrintPage);
PrintDocument.Print("要打印的文档的名称,这个可以随便设置");
}
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
e.PageVisual = new Print1();
}
在SL4 中提供打印功能的是PrintDocument类,所以先实例化一个该类对象。
接着注册一个PrintPage事件,PrintPage事件在打印的时候会触发。
然后调用printDocument的Print方法来打印。
在PrintDocument的PrintPage事件中,PrintPageEventArgs,是打印的参数。
里面可以获取当前打印机的一些信息。
在这里设置PageVisual,也就是要打印的对象就可以了。
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
e.PageVisual = new Print1();
}
全部写好后,可以运行应用程序,点击Print1,弹出打印窗口。打印效果如下图:
当然我们的打印需求不可能这么简单,也许需要设置Print1的内容。假设我们要修改按钮显示的字,那么我们可以这样:
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Print1 printVisual = new Print1();
printVisual.btnSample.Content = "修改后的值,当然也可以从数据库中获取";
e.PageVisual = printVisual;
}
通过设置PrintPageEventArgs 参数的PageVisual对象,我们就可以实现打印那个页面的功能了。
在这里我总结下:
1:确定要打印的内容,然后新建一个UserControl来显示打印的内容。
2:新建PrintDocument对象,注册PrintPage事件,调用Print方法。
3:在PrintPage事件中,构造要打印的对象,然后去数据库中获取数据,然后把数据绑定到控件上,接着把绑定好数据的控件赋值给PrintPageEventArgs的PageVisual 对象。
多页打印问题:
如果要打印的只有一张,那么这种方法应该就够了,但是有时候需要将一份文档打印多张,
比如将上面的按钮打印5张,那么又该如何实现了。
还记得我们上面PrintPageEventArgs的HasMorePages参数吗?
在PrintPage 事件触发后,默认的HasMorePages 为false。将HasMorePages设置为true,可以让PrintPage事件不断被触发。当 HasMorePages 属性为 true,PrintPage 事件将多次发生,直到 HasMorePages 为 false。
假设我们要将上面的按钮打印5张,那么可以设置4次HasMorePages为true,最后设置HasMorePages为false就可以了。
修改后的printDocument_PrintPage 方法如下:
int count = 5;
int printCount = 0;
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Print1 printVisual = new Print1();
printVisual.btnSample.Content = "修改后的值,当然也可以从数据库中获取";
e.PageVisual = printVisual;
printCount++;
if (printCount < count) //如果已经打印的页数小于要打印的页数,说明还需要打印。
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
}
}
有时候需要知道当前打印的是第几页,这可以通过查询printDocument.PrintedPageCount 属性来获得,
在PrintDocument_PrintPage 方法中,sender对象其实就是PrintDocument对象,所以我们可以将它强制类型转换。
假设我们要将上面的5个 Button的内容都修改为1,2,3,4,5.那么我们可以修改代码为:
int count = 5;
int printCount = 0;
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
PrintDocument printDocument = sender as PrintDocument;
Print1 printVisual = new Print1();
printVisual.btnSample.Content = string.Format("按钮{0}", printDocument.PrintedPageCount);
e.PageVisual = printVisual;
printCount++;
if (printCount < count)
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
}
}
实际上,我们的printCount变量都不需要了,直接使用printDocument.PrintedPageCount 就可以了,具体代码实现由读者自己实现吧。
微软的Bug??
如果你的打印机设置为
那么打印的结果就是*.xps的文件,但是在打印的过程中会弹出提示框,询问保存地址。
如果你在PrintPage事件中打上断点的话,可以看到在询问保存地址的时候,PrintPage方法已经执行了,也就是说PringPage方法会被执行两遍,第一遍并没有真正的打印。
例如:
如果在上图的界面上点击取消,则有可能会导致系统失去响应而卡死,
假设用户点击保存,那么PrintPage事件会再次的触发。
但是由于已经打印了一次了,所以有可能导致在多页打印的时候出现问题。
使用两个标志变量可以解决这个问题。
例如修改代码为:
int count = 5;
int printCount = 0;
/// <summary>
/// 是否是第一次打印,因为只有第二次打印的时候才开始真正的打印。
/// </summary>
private bool isInitialized = false;
private bool realPrint = false;
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
PrintDocument printDocument = sender as PrintDocument;
int currentPage = printDocument.PrintedPageCount;
#region 因为要经过两次,第一次是初始化,而第二次才是真正的打印,而两次PrintedPageCount都是0
if (currentPage == 0)
{
if (isInitialized) //如果已经初始化,则设置realPrint为true
{
realPrint = true;
}
isInitialized = true; //运行到这里,说明已经初始化了。
}
#endregion
if (realPrint)
{
//PrintDocument printDocument = sender as PrintDocument;
Print1 printVisual = new Print1();
printVisual.btnSample.Content = string.Format("按钮{0}", printDocument.PrintedPageCount);
e.PageVisual = printVisual;
printCount++;
if (printCount < count)
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
}
}
}
因为两次打印,第一次可以被认为是初始化,第二次可以被认为是打印机开始真正的打印,
所以可以使用两个变量isInitialized 和realPrint 来分别表示是初始化还是真实的打印。
在执行第一遍的时候printDocument.PrintedPageCount ==0,在这时候将isInitialized 设置为true。
在执行第二遍的时候,因为isInitialized ==true,所以可以将realPrint设置为true。
在后面的代码中只需要判断realPrint为true就可以了。
相关文章
- 这篇文章主要介绍了js如何实现浏览器打印功能,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-15
- 这篇文章主要为大家详细介绍了vue实现页面打印自动分页的两种方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-29
- 这篇文章主要介绍了c#如何获取已安装的打印机并调用打印文件,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2020-12-08
Springboot+MDC+traceId日志中打印唯一traceId
本文主要介绍了Springboot+MDC+traceId日志中打印唯一traceId,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-10-17- 这篇文章主要介绍了C#操作excel打印的示例,帮助大家利用c#打印表格,提高办公效率,感兴趣的朋友可以了解下...2020-12-08
- 这篇文章主要介绍了C#基本打印事件用法,实例分析了C#中print打印及DrawString文本字符串绘制等相关技巧,需要的朋友可以参考下...2020-06-25
- C# 实现简单打印的实例代码,需要的朋友可以参考一下...2020-06-25
- web打印 window.print()介绍,需要的朋友可以参考一下...2020-06-25
- 这篇文章主要介绍了C语言打印华氏-摄氏温度对照表的方法,涉及C语言字符串与数字操作的相关技巧,非常简单实用,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了C#打印PDF文档的10种方法(小结),可分多种情况来进行,如设置静默打印、指定打印页码范围和打印纸张大小、双面打印、黑白打印等等,一共分成10种等,感兴趣的可以了解一下...2020-06-25
- 这篇文章介绍了asp.net css控制打印功能方法实例,有需要的可以参考一下...2021-09-22
- 这篇文章主要介绍了C#打印绘图的实现方法,涉及C#针对图片的绘制与打印相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 朋友要求在前段时间完成的新闻的网站上加上一个功能,就是在每篇新闻浏览的页面, 加一个打印铵钮。让用户一点打印,能把整篇文章打印...2021-09-22
- 今天小编就为大家分享一篇从训练好的tensorflow模型中打印训练变量实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-22
- 这篇文章主要介绍了SpringBoot打印POST请求原始入参body体方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-12
- 在项目中,有时需要打印页面的表格,所以下面这篇文章主要给大家介绍了关于vue打印功能实现的两种方法,以及批量打印的完整代码,需要的朋友可以参考下...2021-06-17
Python字符串对齐、删除字符串不需要的内容以及格式化打印字符
这篇文章主要给大家介绍了关于Python字符串对齐、删除字符串不需要的内容以及格式化打印字符的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-01-25- 这篇文章主要介绍了WPF/Silverlight实现图片局部放大的方法,结合实例形式分析了WPF/Silverlight针对图片属性操作相关实现技巧,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了C#实现打印与打印预览功能的思路及代码,有需要的朋友可以参考一下...2020-06-25
- 这篇文章主要介绍了C# 打印网页不显示页眉页脚的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25