欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于Silverlight打印的使用详解,是否为微软的Bug问题

程序员文章站 2023-12-17 13:15:34
1:新建silverlight4 应用程序,名称为slstudy。建好后如下: 2:在slstudy下新建silverlight用户控件,print1.xaml作为...

1:新建silverlight4 应用程序,名称为slstudy。建好后如下:

基于Silverlight打印的使用详解,是否为微软的Bug问题

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,是打印的参数。

里面可以获取当前打印机的一些信息。

基于Silverlight打印的使用详解,是否为微软的Bug问题

在这里设置pagevisual,也就是要打印的对象就可以了。

复制代码 代码如下:

void printdocument_printpage(object sender, printpageeventargs e)
{
  e.pagevisual = new print1();
}

全部写好后,可以运行应用程序,点击print1,弹出打印窗口。打印效果如下图:

基于Silverlight打印的使用详解,是否为微软的Bug问题

当然我们的打印需求不可能这么简单,也许需要设置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??

如果你的打印机设置为

基于Silverlight打印的使用详解,是否为微软的Bug问题

那么打印的结果就是*.xps的文件,但是在打印的过程中会弹出提示框,询问保存地址。

如果你在printpage事件中打上断点的话,可以看到在询问保存地址的时候,printpage方法已经执行了,也就是说pringpage方法会被执行两遍,第一遍并没有真正的打印。

例如:

基于Silverlight打印的使用详解,是否为微软的Bug问题

基于Silverlight打印的使用详解,是否为微软的Bug问题 

如果在上图的界面上点击取消,则有可能会导致系统失去响应而卡死,

假设用户点击保存,那么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就可以了。

上一篇:

下一篇: