Progress.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. using System.ComponentModel;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Windows.Media.Imaging;
  6. using FluentResults;
  7. namespace InABox.WPF
  8. {
  9. public class ProgressSection
  10. {
  11. public ProgressSection(string message, Action action)
  12. {
  13. Message = message;
  14. Action = action;
  15. }
  16. public string Message { get; set; }
  17. public Action Action { get; set; }
  18. }
  19. public static class Progress
  20. {
  21. private static ProgressForm? form;
  22. public static BitmapImage? DisplayImage { get; set; }
  23. public static bool IsVisible => form != null;
  24. public static void ShowModal(params ProgressSection[] sections)
  25. {
  26. if (!sections.Any())
  27. return;
  28. var progress = new ProgressForm
  29. {
  30. DisplayImage = DisplayImage
  31. };
  32. progress.Activated += (_, args) =>
  33. {
  34. progress.Dispatcher.Invoke(() =>
  35. {
  36. foreach (var section in sections)
  37. {
  38. progress.Progress.Content = section.Message;
  39. section.Action();
  40. }
  41. progress.Close();
  42. });
  43. };
  44. progress.ShowActivated = true;
  45. progress.ShowDialog();
  46. }
  47. /// <summary>
  48. /// Shows progress dialog modally, with a cancel button.
  49. /// </summary>
  50. /// <param name="message"></param>
  51. /// <param name="cancelButtonText"></param>
  52. /// <param name="work"></param>
  53. /// <returns>Whether the progress was completed without cancelling.</returns>
  54. public static bool ShowModal(string message, string cancelButtonText, Action<IProgress<string>, CancellationToken> work)
  55. {
  56. var cancellationTokenSource = new CancellationTokenSource();
  57. var progress = new ProgressForm(cancelButtonText)
  58. {
  59. DisplayImage = DisplayImage
  60. };
  61. progress.Progress.Content = message;
  62. progress.Loaded += (_, args) =>
  63. {
  64. var worker = new BackgroundWorker();
  65. var update = new Progress<string>(data => progress.Progress.Content = data);
  66. progress.OnCancelled += () =>
  67. {
  68. cancellationTokenSource.Cancel();
  69. progress.Close();
  70. };
  71. worker.DoWork += (o, e) => work(update, cancellationTokenSource.Token);
  72. worker.RunWorkerCompleted +=
  73. (o, e) => progress.Close();
  74. worker.RunWorkerAsync();
  75. };
  76. progress.ShowDialog();
  77. return !cancellationTokenSource.IsCancellationRequested;
  78. }
  79. public static Result<T> ShowModal<T>(String message, Func<IProgress<string>, Result<T>> work)
  80. {
  81. Result<T> result = Result.Fail<T>("Incomplete");
  82. Exception? exception = null;
  83. var progress = new ProgressForm
  84. {
  85. DisplayImage = DisplayImage
  86. };
  87. progress.Progress.Content = message;
  88. progress.Loaded += (_, args) =>
  89. {
  90. var worker = new BackgroundWorker();
  91. var update = new Progress<string>(data => progress.Progress.Content = data);
  92. progress.OnCancelled += () =>
  93. {
  94. worker.CancelAsync();
  95. };
  96. worker.DoWork += (o, e) =>
  97. {
  98. try
  99. {
  100. result = work(update);
  101. }
  102. catch (Exception ex)
  103. {
  104. result = Result.Fail<T>(ex.Message);
  105. }
  106. };
  107. worker.RunWorkerCompleted +=
  108. (o, e) => progress.Close();
  109. worker.RunWorkerAsync();
  110. };
  111. progress.ShowDialog();
  112. return result;
  113. }
  114. public static void ShowModal(string message, Action<IProgress<string>> work)
  115. {
  116. Exception? exception = null;
  117. var progress = new ProgressForm
  118. {
  119. DisplayImage = DisplayImage
  120. };
  121. progress.Progress.Content = message;
  122. progress.Loaded += (_, args) =>
  123. {
  124. var worker = new BackgroundWorker();
  125. var update = new Progress<string>(data => progress.Progress.Content = data);
  126. progress.OnCancelled += () =>
  127. {
  128. worker.CancelAsync();
  129. };
  130. worker.DoWork += (o, e) =>
  131. {
  132. try
  133. {
  134. work(update);
  135. }
  136. catch (Exception ex)
  137. {
  138. exception = ex;
  139. }
  140. };
  141. worker.RunWorkerCompleted +=
  142. (o, e) => progress.Close();
  143. worker.RunWorkerAsync();
  144. };
  145. progress.ShowDialog();
  146. if(exception is not null)
  147. {
  148. throw exception;
  149. }
  150. }
  151. public static void Show(string message)
  152. {
  153. if (form == null)
  154. {
  155. form = new ProgressForm
  156. {
  157. DisplayImage = DisplayImage
  158. };
  159. form.Show();
  160. }
  161. form.UpdateWindow(message);
  162. }
  163. public static void SetMessage(string message)
  164. {
  165. form?.UpdateWindow(message);
  166. }
  167. public static void Close()
  168. {
  169. form?.CloseWindow();
  170. form = null;
  171. }
  172. }
  173. }