问题
My application prints (to a printer) the information shown on screen (using the Canvas control) N times.
The process is
The user clicks a button (called Print).
Update the Canvas with text (normally from a database but for the code below, it's hard coded)
Print to printer
Update the Canvas with new text (again from a database but for the code below, it's hard coded)
Print to printer
However, I can't get this to work as explained in the above process- the printer only prints the last update made.
To make this issue replicable, I enclose the code below
My XAML
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Canvas Margin="0,0,0,88" Name="canvas1">
<TextBlock Text="Hello World" Name="TextBlock1" />
</Canvas>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="0,245,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
</Window>
and my code behind
using System;
using System.Windows;
using System.Printing;
using System.Windows.Threading;
using System.Windows.Controls;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
PrintDialog dialog = new PrintDialog();
for (int i = 1; i < 3; i++)
{
//showing this message box fixes the issue
//MessageBox.Show("01");
updateTextblock(i);
//use the dispatcher object to ensure all renders and databinding are completed before sending to print
DispatcherOperation disO;
disO = Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(delegate
{
print(dialog);
}
));
disO.Wait()
}
}
private void print(PrintDialog dialog)
{
//select printer auotmatically
PrintQueue queue = new LocalPrintServer().GetPrintQueue("Canon MG160 series WS");
//assign the printer
dialog.PrintQueue = queue;
dialog.PrintVisual(canvas1, "");
}
private void updateTextblock(int i)
{
TextBlock1.Text = "Number " + i.ToString();
}
}
}
The only thing which prints is Number 2
Although it has iterated and updated the canvas with Number 1 it never prints (a blank page is printed).
Any ideas what it is I need to do so each Canvas prints? Although I can get it to work by showing the messagebox it defeats the purpose of it being automated.
EDIT: I am now getting an error message from my printer - "Another computer is using the printer." According to other websites, I have to wait until one job finishes and then the second will start automatically but sadly, it never does.
回答1:
Use PrintDialog dialog = new PrintDialog(); inside for loop Use this function
private void button1_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 3; i++)
{
PrintDialog dialog = new PrintDialog();
//showing this message box fixes the issue
//MessageBox.Show("01");
updateTextblock(i);
//use the dispatcher object to ensure all renders and databinding are completed before sending to print
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(delegate
{
print(dialog);
}
));
}
}
回答2:
The answer (sorry the code is not exactly the same as the question but it's so simple it should be easy to follow. Thank you every one.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 2; i++)
{
result res = null;
if (i == 0)
res = new result { Comments = "First Time Round" };
if (i == 1)
res = new result { Comments = "Total hard type" };
Dispatcher.Invoke(DispatcherPriority.Loaded, new Action(delegate
{
this.DataContext = res;
}
));
System.Threading.Thread.Sleep(500);
Dispatcher.Invoke(DispatcherPriority.Loaded, new Action(delegate
{
PrintDialog dialog = new PrintDialog();
dialog.PrintVisual(this.canvas1, "");
}
));
System.Threading.Thread.Sleep(500);
}
}
}
class result
{
public string Comments { get; set; }
}
}
回答3:
Your UpdateText method is all wrong. Each time you call the method you are creating a new string in the textblock. So as a result all you will see is the last call to the routine.
Instead you should be appending to the text instead of replacing the text.
回答4:
The BeginInvoke returns a DispatcherOperation. If you call Wait on it before continuing in the for loop, the textbox will not be updated, until the first print has been performed.
来源:https://stackoverflow.com/questions/10902791/c-sharp-printing-with-wpf