1 sing System.Linq;
2 using System.Printing;
3 using System.Windows;
4 using System.Windows.Controls;
5 using System.Windows.Documents;
6 using System.Windows.Markup;
7 using System.Windows.Media;
8 using Telerik.Windows.Controls;
9 using Telerik.Windows.Controls.GridView;
10
11 namespace YourNamespaceHere
12 {
13 /// <summary>
14 /// Support Printing Related Methods
15 /// </summary>
16 public static class PrintExtensions
17 {
18 #region ___________ Properties ____________________________________________________________________________________________
19 /// <summary>
20 /// Zoom Enumeration to specify how pages are stretched in print and preview
21 /// </summary>
22 public enum ZoomType
23 {
24 /// <summary>
25 /// 100% of normal size
26 /// </summary>
27 Full,
28
29 /// <summary>
30 /// Page Width (fit so one page stretches to full width)
31 /// </summary>
32 Width,
33
34 /// <summary>
35 /// Page Height (fit so one page stretches to full height)
36 /// </summary>
37 Height,
38
39 /// <summary>
40 /// Display two columsn of pages
41 /// </summary>
42 TwoWide
43 };
44 #endregion
45 #region ___________ Methods _______________________________________________________________________________________________
46 /// <summary>
47 /// Print element to a document
48 /// </summary>
49 /// <param name="element">GUI Element to Print</param>
50 /// <param name="dialog">Reference to Print Dialog</param>
51 /// <param name="orientation">Page Orientation (i.e. Portrait vs. Landscape)</param>
52 /// <returns>Destination document</returns>
53 static FixedDocument ToFixedDocument(FrameworkElement element, PrintDialog dialog, PageOrientation orientation = PageOrientation.Portrait)
54 {
55 dialog.PrintTicket.PageOrientation = orientation;
56 PrintCapabilities capabilities = dialog.PrintQueue.GetPrintCapabilities(dialog.PrintTicket);
57 Size pageSize = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight);
58 Size extentSize = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
59
60 FixedDocument fixedDocument = new FixedDocument();
61
62 element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
63 element.Arrange(new Rect(new Point(0, 0), element.DesiredSize));
64
65 for (double y = 0; y < element.DesiredSize.Height; y += extentSize.Height)
66 {
67 for (double x = 0; x < element.DesiredSize.Width; x += extentSize.Width)
68 {
69 VisualBrush brush = new VisualBrush(element);
70 brush.Stretch = Stretch.None;
71 brush.AlignmentX = AlignmentX.Left;
72 brush.AlignmentY = AlignmentY.Top;
73 brush.ViewboxUnits = BrushMappingMode.Absolute;
74 brush.TileMode = TileMode.None;
75 brush.Viewbox = new Rect(x, y, extentSize.Width, extentSize.Height);
76
77 PageContent pageContent = new PageContent();
78 FixedPage page = new FixedPage();
79 ((IAddChild)pageContent).AddChild(page);
80
81 fixedDocument.Pages.Add(pageContent);
82 page.Width = pageSize.Width;
83 page.Height = pageSize.Height;
84
85 Canvas canvas = new Canvas();
86 FixedPage.SetLeft(canvas, capabilities.PageImageableArea.OriginWidth);
87 FixedPage.SetTop(canvas, capabilities.PageImageableArea.OriginHeight);
88 canvas.Width = extentSize.Width;
89 canvas.Height = extentSize.Height;
90 canvas.Background = brush;
91
92 page.Children.Add(canvas);
93 }
94 }
95 return fixedDocument;
96 }
97
98 /// <summary>
99 /// Convert GridView to Printer-Friendly version of a GridView
100 /// </summary>
101 /// <param name="source">Input GridView</param>
102 /// <returns>Printer-Friendly version of source</returns>
103 static GridViewDataControl ToPrintFriendlyGrid(GridViewDataControl source)
104 {
105 RadGridView grid = new RadGridView();
106
107 grid.ItemsSource = source.ItemsSource;
108 grid.RowIndicatorVisibility = Visibility.Collapsed;
109 grid.ShowGroupPanel = false;
110 grid.CanUserFreezeColumns = false;
111 grid.IsFilteringAllowed = false;
112 grid.AutoExpandGroups = true;
113 grid.AutoGenerateColumns = false;
114
115 foreach (GridViewDataColumn column in source.Columns.OfType<GridViewDataColumn>())
116 {
117 GridViewDataColumn newColumn = new GridViewDataColumn();
118 newColumn.Width = column.ActualWidth;
119 newColumn.DisplayIndex = column.DisplayIndex;
120 //newColumn.DataMemberBinding = new System.Windows.Data.Binding(column.UniqueName);
121 newColumn.DataMemberBinding = column.DataMemberBinding; // Better to just copy the references to get all the custom formatting
122 newColumn.DataFormatString = column.DataFormatString;
123 newColumn.TextAlignment = column.TextAlignment;
124 newColumn.Header = column.Header;
125 newColumn.Footer = column.Footer;
126 grid.Columns.Add(newColumn);
127 }
128
129 StyleManager.SetTheme(grid, StyleManager.GetTheme(grid));
130
131 grid.SortDescriptors.AddRange(source.SortDescriptors);
132 grid.GroupDescriptors.AddRange(source.GroupDescriptors);
133 grid.FilterDescriptors.AddRange(source.FilterDescriptors);
134
135 return grid;
136 }
137
138 /// <summary>
139 /// Perform a Print Preview on GridView source
140 /// </summary>
141 /// <param name="source">Input GridView</param>
142 /// <param name="orientation">Page Orientation (i.e. Portrait vs. Landscape)</param>
143 /// <param name="zoom">Zoom Enumeration to specify how pages are stretched in print and preview</param>
144 public static void PrintPreview(GridViewDataControl source, PageOrientation orientation = PageOrientation.Landscape, ZoomType zoom = ZoomType.TwoWide)
145 {
146 Window window = new Window();
147 window.Title = "Print Preview";
148 if (!string.IsNullOrWhiteSpace(source.ToolTip as string)) window.Title += " of " + source.ToolTip;
149 window.Width = SystemParameters.PrimaryScreenWidth * 0.92;
150 window.Height = SystemParameters.WorkArea.Height;
151 window.Left = constrain(SystemParameters.VirtualScreenWidth - SystemParameters.PrimaryScreenWidth, 0, SystemParameters.VirtualScreenWidth - 11);
152 window.Top = constrain(0, 0, SystemParameters.VirtualScreenHeight - 25);
153
154 DocumentViewer viewer = new DocumentViewer();
155 viewer.Document = ToFixedDocument(ToPrintFriendlyGrid(source), new PrintDialog(), orientation);
156 Zoom(viewer, zoom);
157 window.Content = viewer;
158
159 window.ShowDialog();
160 }
161
162 /// <summary>
163 /// Constrain val to the range [val_min, val_max]
164 /// </summary>
165 /// <param name="val">Value to be constrained</param>
166 /// <param name="val_min">Minimum that will be returned if val is less than val_min</param>
167 /// <param name="val_max">Maximum that will be returned if val is greater than val_max</param>
168 /// <returns>val in [val_min, val_max]</returns>
169 private static double constrain(double val, double val_min, double val_max)
170 {
171 if (val < val_min) return val_min;
172 else if (val > val_max) return val_max;
173 else return val;
174 }
175
176 /// <summary>
177 /// Perform a Print on GridView source
178 /// </summary>
179 /// <param name="source">Input GridView</param>
180 /// <param name="showDialog">True to show print dialog before printing</param>
181 /// <param name="orientation">Page Orientation (i.e. Portrait vs. Landscape)</param>
182 /// <param name="zoom">Zoom Enumeration to specify how pages are stretched in print and preview</param>
183 public static void Print(GridViewDataControl source, bool showDialog = true, PageOrientation orientation = PageOrientation.Landscape, ZoomType zoom = ZoomType.TwoWide)
184 {
185 PrintDialog dialog = new PrintDialog();
186 bool? dialogResult = showDialog ? dialog.ShowDialog() : true;
187
188 if (dialogResult == true)
189 {
190 DocumentViewer viewer = new DocumentViewer();
191 viewer.Document = ToFixedDocument(ToPrintFriendlyGrid(source), dialog, orientation);
192 Zoom(viewer, zoom);
193 dialog.PrintDocument(viewer.Document.DocumentPaginator, "");
194 }
195 }
196
197 /// <summary>
198 /// Scale viewer to size specified by zoom
199 /// </summary>
200 /// <param name="viewer">Document to zoom</param>
201 /// <param name="zoom">Zoom Enumeration to specify how pages are stretched in print and preview</param>
202 public static void Zoom(DocumentViewer viewer, ZoomType zoom)
203 {
204 switch (zoom)
205 {
206 case ZoomType.Height: viewer.FitToHeight(); break;
207 case ZoomType.Width: viewer.FitToWidth(); break;
208 case ZoomType.TwoWide: viewer.FitToMaxPagesAcross(2); break;
209 case ZoomType.Full: break;
210 }
211 }
212 #endregion
213 }