WpfPreviewControl.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. using FastReport.Utils;
  2. using System;
  3. using System.ComponentModel;
  4. using System.IO;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. namespace FastReport.Preview
  10. {
  11. /// <summary>
  12. /// Represents a WPF control used to preview a report.
  13. /// </summary>
  14. /// <remarks>
  15. /// To use this control, place it on a form and link it to a report using the report's
  16. /// <see cref="FastReport.Report.WpfPreview"/> property. To show a report, call
  17. /// the <b>Report.Show</b> method:
  18. /// <code>
  19. /// report1.WpfPreview = previewControl1;
  20. /// report1.Show();
  21. /// </code>
  22. /// <para>Use this control's methods such as <see cref="Print"/>, <see cref="Save()"/> etc. to
  23. /// handle the preview. Call <see cref="Clear"/> method to clear the preview.</para>
  24. /// <para>You can specify whether the standard toolbar is visible in the <see cref="ToolbarVisible"/>
  25. /// property. The <see cref="StatusbarVisible"/> property allows you to hide/show the statusbar.
  26. /// </para>
  27. /// </remarks>
  28. public partial class WpfPreviewControl : UserControl, INotifyPropertyChanged
  29. {
  30. /// <summary>
  31. /// Gets inner preview control.
  32. /// </summary>
  33. public PreviewControl InnerPreview { get; }
  34. /// <summary>
  35. /// Specifies the set of buttons available in the toolbar.
  36. /// </summary>
  37. public PreviewButtons Buttons
  38. {
  39. get => InnerPreview.Buttons;
  40. set => InnerPreview.Buttons = value;
  41. }
  42. /// <summary>
  43. /// Gets or sets a value indicating whether the toolbar is visible.
  44. /// </summary>
  45. public bool ToolbarVisible
  46. {
  47. get => InnerPreview.ToolbarVisible;
  48. set => InnerPreview.ToolbarVisible = value;
  49. }
  50. /// <summary>
  51. /// Gets or sets a value indicating whether the statusbar is visible.
  52. /// </summary>
  53. public bool StatusbarVisible
  54. {
  55. get => InnerPreview.StatusbarVisible;
  56. set => InnerPreview.StatusbarVisible = value;
  57. }
  58. /// <summary>
  59. /// Gets or sets the visual style.
  60. /// </summary>
  61. public UIStyle UIStyle
  62. {
  63. get => InnerPreview.UIStyle;
  64. set => InnerPreview.UIStyle = value;
  65. }
  66. /// <summary>
  67. /// Gets or sets a color used to draw the background area.
  68. /// </summary>
  69. /// <remarks>
  70. /// In order to use this property, you must also set the <see cref="UseBackColor"/> property to true.
  71. /// </remarks>
  72. public Color BackColor
  73. {
  74. get => System.Windows.Forms.Helper.GetColor(InnerPreview.BackColor);
  75. set => InnerPreview.BackColor = System.Windows.Forms.Helper.GetColor(value);
  76. }
  77. /// <summary>
  78. /// Gets or sets a value indicating that the BackColor property must be used to draw the background area.
  79. /// </summary>
  80. /// <remarks>
  81. /// By default, the background area is drawn using the color defined in the current <b>UIStyle</b>.
  82. /// </remarks>
  83. public bool UseBackColor
  84. {
  85. get => InnerPreview.UseBackColor;
  86. set => InnerPreview.UseBackColor = value;
  87. }
  88. /// <summary>
  89. /// Gets or sets the color of active page border.
  90. /// </summary>
  91. public Color ActivePageBorderColor
  92. {
  93. get => System.Windows.Forms.Helper.GetColor(InnerPreview.ActivePageBorderColor);
  94. set => InnerPreview.ActivePageBorderColor = System.Windows.Forms.Helper.GetColor(value);
  95. }
  96. /// <summary>
  97. /// Gets a reference to the report.
  98. /// </summary>
  99. public Report Report => InnerPreview.Report;
  100. /// <summary>
  101. /// Gets the value indicating that async report is running.
  102. /// </summary>
  103. /// <remarks>
  104. /// This value can be used to abort the report when you close the form that contains the report preview control.
  105. /// </remarks>
  106. public bool IsAsyncReportRunning => InnerPreview.IsAsyncReportRunning;
  107. /// <summary>
  108. /// Occurs when the current page is changed.
  109. /// </summary>
  110. public event EventHandler PageChanged
  111. {
  112. add => InnerPreview.PageChanged += value;
  113. remove => InnerPreview.PageChanged -= value;
  114. }
  115. #region ICommands
  116. public PreviewCommand cmdPrint { get; }
  117. public PreviewCommand cmdSave { get; }
  118. public PreviewCommand cmdLoad { get; }
  119. public PreviewCommand cmdSendEmail { get; }
  120. public PreviewCommand cmdFind { get; }
  121. public PreviewCommand cmdFindNext { get; }
  122. public PreviewCommand cmdFirst { get; }
  123. public PreviewCommand cmdPrior { get; }
  124. public PreviewCommand cmdNext { get; }
  125. public PreviewCommand cmdLast { get; }
  126. public PreviewCommand cmdZoomIn { get; }
  127. public PreviewCommand cmdZoomOut { get; }
  128. public PreviewCommand cmdZoomPageWidth { get; }
  129. public PreviewCommand cmdZoomWholePage { get; }
  130. public PreviewCommand cmdEditPage { get; }
  131. public PreviewCommand cmdEditWatermark { get; }
  132. public PreviewCommand cmdPageSetup { get; }
  133. public PreviewCommand cmdClear { get; }
  134. public event PropertyChangedEventHandler PropertyChanged;
  135. #endregion
  136. #region Preview commands
  137. /// <summary>
  138. /// Prints the current report.
  139. /// </summary>
  140. /// <returns><b>true</b> if report was printed; <b>false</b> if user cancels the "Print" dialog.</returns>
  141. public bool Print() => InnerPreview.Print();
  142. /// <summary>
  143. /// Saves the current report to a .fpx file using the "Save FIle" dialog.
  144. /// </summary>
  145. public void Save() => InnerPreview.Save();
  146. /// <summary>
  147. /// Saves the current report to a specified .fpx file.
  148. /// </summary>
  149. public void Save(string fileName) => InnerPreview.Save(fileName);
  150. /// <summary>
  151. /// Saves the current report to a stream.
  152. /// </summary>
  153. public void Save(Stream stream) => InnerPreview.Save(stream);
  154. /// <summary>
  155. /// Loads the report from a .fpx file using the "Open File" dialog.
  156. /// </summary>
  157. public void Load() => InnerPreview.Load();
  158. /// <summary>
  159. /// Loads the report from a specified .fpx file.
  160. /// </summary>
  161. public void Load(string fileName) => InnerPreview.Load(fileName);
  162. /// <summary>
  163. /// Load the report from a stream.
  164. /// </summary>
  165. /// <param name="stream">The stream to load from.</param>
  166. public void Load(Stream stream) => InnerPreview.Load(stream);
  167. /// <summary>
  168. /// Sends an email.
  169. /// </summary>
  170. public void SendEmail() => InnerPreview.SendEmail();
  171. /// <summary>
  172. /// Finds the text in the current report using the "Find Text" dialog.
  173. /// </summary>
  174. public void Find() => InnerPreview.Find();
  175. /// <summary>
  176. /// Finds the specified text in the current report.
  177. /// </summary>
  178. /// <param name="text">Text to find.</param>
  179. /// <param name="matchCase">A value indicating whether the search is case-sensitive.</param>
  180. /// <param name="wholeWord">A value indicating whether the search matches whole words only.</param>
  181. /// <returns><b>true</b> if text found.</returns>
  182. public bool Find(string text, bool matchCase, bool wholeWord) => InnerPreview.Find(text, matchCase, wholeWord);
  183. /// <summary>
  184. /// Finds the next occurence of text specified in the <b>Find</b> method.
  185. /// </summary>
  186. /// <returns><b>true</b> if text found.</returns>
  187. public bool FindNext() => InnerPreview.FindNext();
  188. /// <summary>
  189. /// Navigates to the first page.
  190. /// </summary>
  191. public void First() => InnerPreview.First();
  192. /// <summary>
  193. /// Navigates to the previuos page.
  194. /// </summary>
  195. public void Prior() => InnerPreview.Prior();
  196. /// <summary>
  197. /// Navigates to the next page.
  198. /// </summary>
  199. public void Next() => InnerPreview.Next();
  200. /// <summary>
  201. /// Navigates to the last page.
  202. /// </summary>
  203. public void Last() => InnerPreview.Last();
  204. /// <summary>
  205. /// Gets or sets the current page number.
  206. /// </summary>
  207. /// <remarks>
  208. /// This value is 1-based.
  209. /// </remarks>
  210. public int PageNo
  211. {
  212. get => InnerPreview.PageNo;
  213. set => InnerPreview.PageNo = value;
  214. }
  215. /// <summary>
  216. /// Gets the pages count in the current report.
  217. /// </summary>
  218. public int PageCount => InnerPreview.PageCount;
  219. /// <summary>
  220. /// Gets or sets the zoom factor.
  221. /// </summary>
  222. /// <remarks>
  223. /// <b>1</b> corresponds to 100% zoom.
  224. /// </remarks>
  225. public float Zoom
  226. {
  227. get => InnerPreview.Zoom;
  228. set => InnerPreview.Zoom = value;
  229. }
  230. /// <summary>
  231. /// Zooms in.
  232. /// </summary>
  233. public void ZoomIn() => InnerPreview.ZoomIn();
  234. /// <summary>
  235. /// Zooms out.
  236. /// </summary>
  237. public void ZoomOut() => InnerPreview.ZoomOut();
  238. /// <summary>
  239. /// Zooms to fit the page width.
  240. /// </summary>
  241. public void ZoomPageWidth() => InnerPreview.ZoomPageWidth();
  242. /// <summary>
  243. /// Zooms to fit the whole page.
  244. /// </summary>
  245. public void ZoomWholePage() => InnerPreview.ZoomWholePage();
  246. /// <summary>
  247. /// Edits the current page in the designer.
  248. /// </summary>
  249. public void EditPage() => InnerPreview.EditPage();
  250. /// <summary>
  251. /// Edits the watermark.
  252. /// </summary>
  253. public void EditWatermark() => InnerPreview.EditWatermark();
  254. /// <summary>
  255. /// Edits the page settings.
  256. /// </summary>
  257. public void PageSetup() => InnerPreview.PageSetup();
  258. /// <summary>
  259. /// Navigates to the specified position inside a specified page.
  260. /// </summary>
  261. /// <param name="pageNo">The page number (1-based).</param>
  262. /// <param name="point">The position inside a page, in pixels.</param>
  263. public void PositionTo(int pageNo, Point point) => InnerPreview.PositionTo(pageNo, new System.Drawing.PointF((float)point.X, (float)point.Y));
  264. /// <summary>
  265. /// Clears the preview.
  266. /// </summary>
  267. public void Clear() => InnerPreview.Clear();
  268. /// <summary>
  269. /// Refresh the report.
  270. /// </summary>
  271. public void RefreshReport() => InnerPreview.RefreshReport();
  272. /// <summary>
  273. /// Displays the text in the status bar.
  274. /// </summary>
  275. /// <param name="text">Text to display.</param>
  276. public void ShowStatus(string text) => InnerPreview.ShowStatus(text);
  277. #endregion
  278. private PreviewCommand CreateCmd(Action action) => new PreviewCommand(action);
  279. /// <summary>
  280. /// Initializes a new instance of the <see cref="WpfPreviewControl"/> class.
  281. /// </summary>
  282. public WpfPreviewControl()
  283. {
  284. InnerPreview = new PreviewControl();
  285. var control = InnerPreview.control;
  286. control.Width = double.NaN;
  287. control.Height = double.NaN;
  288. control.HorizontalAlignment = HorizontalAlignment.Stretch;
  289. control.VerticalAlignment = VerticalAlignment.Stretch;
  290. Content = control;
  291. UseLayoutRounding = true;
  292. Loaded += (s, e) =>
  293. {
  294. System.Windows.Forms.DpiRescaler.Install(Window.GetWindow(this), InnerPreview, this, (s, e) => InnerPreview.UpdateDpiDependencies());
  295. };
  296. InnerPreview.PageChanged += (s, e) =>
  297. {
  298. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PageNo)));
  299. };
  300. cmdPrint = CreateCmd(() => InnerPreview.Print());
  301. cmdSave = CreateCmd(InnerPreview.Save);
  302. cmdLoad = CreateCmd(InnerPreview.Load);
  303. cmdSendEmail = CreateCmd(InnerPreview.SendEmail);
  304. cmdFind = CreateCmd(InnerPreview.Find);
  305. cmdFindNext = CreateCmd(() => InnerPreview.FindNext());
  306. cmdFirst = CreateCmd(InnerPreview.First);
  307. cmdPrior = CreateCmd(InnerPreview.Prior);
  308. cmdNext = CreateCmd(InnerPreview.Next);
  309. cmdLast = CreateCmd(InnerPreview.Last);
  310. cmdZoomIn = CreateCmd(InnerPreview.ZoomIn);
  311. cmdZoomOut = CreateCmd(InnerPreview.ZoomOut);
  312. cmdZoomPageWidth = CreateCmd(InnerPreview.ZoomPageWidth);
  313. cmdZoomWholePage = CreateCmd(InnerPreview.ZoomWholePage);
  314. cmdEditPage = CreateCmd(InnerPreview.EditPage);
  315. cmdEditWatermark = CreateCmd(InnerPreview.EditWatermark);
  316. cmdPageSetup = CreateCmd(InnerPreview.PageSetup);
  317. cmdClear = CreateCmd(InnerPreview.Clear);
  318. }
  319. }
  320. }