Printing from WPF
本文关键字:WPF from Printing | 更新日期: 2023-09-27 18:00:25
我有一个WPF数据输入屏幕/窗口,我想为其提供打印输出。(准确地说,这是一个UserControl,我已经将其设置为在我想要打印的TabControl中作为TabItem工作。)
为了更好地打印,我进行了几次布局转换,将窗口缩放到纸张大小,并更改应用程序的外观。"打印皮肤"将背景更改为白色,并删除标题标签等的背景。
这非常有效,同时MessageBox.Show()
提示告诉我发生了什么。
然而,当我拿出Messagebox.Show提示时,我发现我所有的打印魔法都不起作用,就好像enire打印方法只是:UserControl上的PrintVisual();
。(我已经将其缩小到一个MessageBox,如果不破坏东西,我就无法摆脱它。)
代码(抱歉太长了,我添加了大量评论):
private void PrintStatements()
{
PrintDialog print = new PrintDialog();
/// Needed data
PrintCapabilities capabilities = print.PrintQueue.GetPrintCapabilities(print.PrintTicket);
double pageMargin = 1 / 2.54; // 1cm
double pageWidth = capabilities.PageImageableArea.ExtentWidth - (pageMargin);
double pageLength = capabilities.PageImageableArea.ExtentHeight - (pageMargin);
Size pageSize = new Size(pageWidth, pageLength);
ResourceDictionary resources = new ResourceDictionary();
bool canPrint = print.ShowDialog() ?? false;
if (canPrint)
{
double tabWidth = StatementsTabCtrl.ActualWidth;
double tabHeight = StatementsTabCtrl.ActualHeight;
/// 1. Get tab item content ('currentTabContent')
StatementsTabItem currentTabContent = StatementsTabCtrl.SelectedContent as StatementsTabItem;
/// 2. Get Original Specs of currentTabContent
ResourceDictionary origSkin = Application.Current.Resources;
Size origSize = new Size(currentTabContent.ActualWidth, currentTabContent.ActualHeight);
Transform origTransform = currentTabContent.LayoutTransform;
/// 3. Transform currentTabContent (expose print panels, move stuff around etc) -
//do this inside TabItem class
currentTabContent.SetupPrinting();
/// 4. Make changes outside TabItem (skin, page-scale)
// skin
resources.MergedDictionaries.Add(Application.LoadComponent(new Uri(@"Skin/PrintDictionary.xaml", UriKind.Relative)) as ResourceDictionary);
Application.Current.Resources = resources;
// page-scale
double scale = Math.Min(pageWidth / currentTabContent.ActualWidth,
pageLength / currentTabContent.ActualHeight);
// ****Uncomment next line - printing magic works.**** //
// MessageBox.Show(string.Format("scaling by {0}", scale));
System.Threading.Thread.Sleep(250);
currentTabContent.LayoutTransform = new ScaleTransform(scale, scale);
//Measure and Arrange
currentTabContent.Measure(pageSize);
((UIElement)currentTabContent).Arrange(new Rect(
new Point((capabilities.PageImageableArea.OriginWidth + pageMargin),
(capabilities.PageImageableArea.OriginHeight + pageMargin)), pageSize));
System.Threading.Thread.Sleep(250);
/// 5. Print (Finally!)
print.PrintVisual(currentTabContent, "Print Results");
/// 6. Return everything to normal (undo 3, then 4)
// undo 3.
currentTabContent.TearDownPrinting();
// undo 4.
Application.Current.Resources = origSkin;
scale = Math.Max(currentTabContent.ActualWidth / pageWidth,
currentTabContent.ActualHeight / pageLength);
currentTabContent.LayoutTransform = new ScaleTransform(1 / scale, 1 / scale);
currentTabContent.Measure(origSize);
((UIElement)currentTabContent).Arrange(new Rect(0, 0, tabWidth, tabHeight));
}
}
正如你所看到的,我已经尝试添加了几个System.Threading.Thread.Sleep(250);
,以防它需要更多的时间来识别更改,但这没有效果。PrintDialog()
调用的怪异也是出于类似的原因。用通常的方式称呼它没有什么区别。
有人能告诉我为什么没有MessageBox调用,我的打印功能就不能工作吗?或者告诉我如何模拟MessageBox调用来欺骗程序工作吗?很多很多TIA
您可能缺少的部分是MessageBox.Show();
刷新了UIElement
因此,如果您使用以下代码手动重新刷新UIElement,就足够了
ui.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));// activates ui.InvalidateMeasure();
ui.Arrange(new Rect(new Point(0, 0), ui.DesiredSize)); // activates ui.InvalidateArrange();
ui.UpdateLayout(); // <-- refreshed your UIElement
这至少在我的情况下有效
旁注:
你不应该直接调用ui.Invalidate...
,因为如果你不更改Measure或Arrange,因为UpdateLayout()
不会刷新你的UIElement
AFAIK