1

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

如果我想在 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?

4

5 回答 5

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. 不知道这是否是一般问题,或者只是我的打印机设置的问题。

我从这篇文章中得到了这个想法,其中还提到了使用 ViewBox 的替代解决方案。

于 2012-06-15T07:15:17.377 回答
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) - 这很有效,因为它有足够的时间来确保打印作业已经完成,但它也有点“希望”,我想要更安全的东西。

谢谢大家的建议。

于 2012-06-16T16:27:27.640 回答
0

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

打印视口

于 2012-06-14T14:52:03.333 回答
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);
}

我从这里采购这个想法

于 2012-06-14T15:01:57.133 回答
0

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

于 2012-06-14T14:41:56.527 回答