WPF - 在循环期间打印

时间:2012-06-14 14:25:35

标签: c# wpf binding

我有一个简单的问题,但解决方案似乎很棘手。我想在循环期间使用WPF控件画布进行打印;但是对于每次迭代,我都想用udpate画布控件。

如果我想在WPF中打印画布控件,我可以简单地调用

PrintDialog dialog = new PrintDialog();
dialog.PrintVisual(this.canvas, "");

它按预期打印到我的默认打印机。精彩。

但是,如果我想在循环中多次执行此操作并在每次迭代期间更新画布,则只打印循环的最后一次迭代。

    private void methodName()
    {
        for (int i = 0; i < 2; i++)
        {
            updateTextBox(i.ToString());
            PrintDialog dialog = new PrintDialog();
            dialog.PrintVisual(this.canvas, "");
        }
    }

    private void updateTextBox(string text)
    {
        txtTextBox.Text = text;
    }

知道我需要做些什么来确保我得到2次打印输出,第一次使用txtTextBox.Text值为0,第二次输出值是否为1?

5 个答案:

答案 0 :(得分:1)

我即将在我的应用程序中实现类似的东西,并发现我以前的答案不够好。对我来说问题是虽然画布在每次迭代中都会更新,但在发送到PrintVisual之前它还没有自我渲染。令我惊讶的是,你打印了最后的迭代,我只得到了第一个。无论如何,这就是我使它工作的方式,基本上是在已经挂起的渲染操作之后排队打印命令:

for (int i = 0; i < 2; i++)
{
  updateTextBox(i.ToString());
  this.canvas.InvalidateVisual(); // Maybe not needed in your case

  PrintDialog dialog = new PrintDialog();

  this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, (Action)delegate()
  {
     dialog.PrintVisual(this.canvas, "" + i);
  });
}

是的,它与SalGad的答案和你所指的帖子有些相似(但不完全相同),但我无法对该答案发表评论,所以请尝试这个,它对我有用。

当对打印作业使用空描述时,我也遇到了打印消失的问题,因此+ i。不知道这是一般问题,还是我的打印机设置。

我从this post得到了这个想法,它也提到了使用ViewBox的替代解决方案。

答案 1 :(得分:1)

我解决了。

我删除了所有调度程序对象方法,因此它在单个线程上运行。

要更新画布,我使用了canvas.UpdateLayout()方法。

我还确保在更新下一个画布(下一次迭代)之前已完成打印。

private void methodName()
{
    for (int i = 0; i < 2; i++)
    {
        updateTextBox(i.ToString());

        this.canvas.UpdateLayout();

        PrintDialog dialog = new PrintDialog();
        dialog.PrintVisual(this.canvas, "ABC");

        dialog.PrintQueue.Refresh();

        while (dialog.PrintQueue.NumberOfJobs != 0)
        {
            bool isQueued = false;
            foreach (var job in dialog.PrintQueue.GetPrintJobInfoCollection())
            {
                if (job.Name == "ABC")
                    isQueued = true;
            }

            if (!isQueued)
                break;

            Thread.Sleep(500);
            dialog.PrintQueue.Refresh();
        }
    }
}

private void updateTextBox(string text)
{
    txtTextBox.Text = text;
}

我也可以刚刚完成thread.sleep(3000) - 因为它足够时间确保打印作业已经完成,但它也有点“充满希望”,我想要更安全的东西。

感谢大家的建议。

答案 2 :(得分:0)

如果您打算多次调用PrintVisual,则必须查看PrintDocument和DocumentPaginator。

答案 3 :(得分:0)

只是一个猜测,但是可能值得尝试RenderTargetBitmap强制在每次迭代中渲染画布,然后使用该源创建一个Image,然后可以将其发送到PrintVisual。有关代码示例,请参阅此文章:

Printing viewport

答案 4 :(得分:0)

只是在这里拍摄,但是你可以尝试在每次for循环迭代的开始时刷新WPF画布控件吗?以下是代码段:

// declare this
public static class ExtensionMethods
{
   private static Action EmptyDelegate = delegate() { };

   public static void Refresh(this UIElement uiElement)
   {
      uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
   }
}

// the loop
for (int i = 0; i < 2; i++)
    {
        updateTextBox(i.ToString());
        PrintDialog dialog = new PrintDialog();
        dialog.PrintVisual(this.canvas, "");
    }
}

// update this method
private void updateTextBox(string text)
{
    txtTextBox.Text = text;
    txtTextBox.Refresh();
    Thread.Sleep(500);
}

我从here

采购这个想法