您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

374 行
15 KiB

  1. using BPA.UIControl.Commons;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. namespace BPA.UIControl
  11. {
  12. /// <summary>
  13. /// 消息操作类
  14. /// </summary>
  15. public class Message
  16. {
  17. /// <summary>
  18. /// Transition 动画时长
  19. /// </summary>
  20. public const int TransitionTime = 300;
  21. /// <summary>
  22. /// 所有容器集合
  23. /// </summary>
  24. internal static Dictionary<string, MessageContainer> Containers = new Dictionary<string, MessageContainer>();
  25. /// <summary>
  26. /// 更新容器
  27. /// </summary>
  28. /// <param name="container">容器</param>
  29. /// <param name="identify">标识</param>
  30. internal static void UpdateContainer(MessageContainer container, string identify)
  31. {
  32. if (Containers.ContainsKey(identify))
  33. {
  34. _ = Containers.Remove(identify);
  35. }
  36. Containers.Add(identify, container);
  37. }
  38. private static MessageCard GetMessageCard(MessageType type, object content, int millisecondTimeOut, bool isClearable)
  39. {
  40. isClearable = millisecondTimeOut <= 0 || isClearable;
  41. return new MessageCard
  42. {
  43. Type = type,
  44. Content = content,
  45. IsClearable = isClearable
  46. };
  47. }
  48. /// <summary>
  49. /// 延期关闭消息卡片
  50. /// </summary>
  51. /// <param name="millisecondTimeOut">显示时间,小于 0 时不自动关闭</param>
  52. /// <param name="messageCard">消息卡片</param>
  53. /// <param name="token">取消令牌</param>
  54. private static void DelayCloseMessageCard(int millisecondTimeOut, MessageCard messageCard, CancellationToken token)
  55. {
  56. if (millisecondTimeOut > 0)
  57. {
  58. _ = Task.Run(async () =>
  59. {
  60. await Task.Delay(millisecondTimeOut + TransitionTime, token);
  61. Application.Current.Dispatcher.Invoke(() =>
  62. {
  63. messageCard.IsShow = false;
  64. });
  65. }, token);
  66. }
  67. }
  68. #region 全局
  69. /// <summary>
  70. /// 全局显示
  71. /// </summary>
  72. /// <param name="type">类型</param>
  73. /// <param name="content">内容</param>
  74. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  75. /// <param name="isClearable">是否显示关闭按钮</param>
  76. public static void ShowGlobal(MessageType type, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  77. {
  78. MessageWindow messageWindow = MessageWindow.GetInstance();
  79. messageWindow.Dispatcher.VerifyAccess();
  80. MessageCard messageCard = GetMessageCard(type, content, millisecondTimeOut, isClearable);
  81. CancellationTokenSource cts = new CancellationTokenSource();
  82. messageCard.Close += (sender, e) => messageWindow.RemoveMessageCard(messageCard);
  83. messageCard.MouseEnter += (sender, e) => cts.Cancel();
  84. messageCard.MouseLeave += (sender, e) =>
  85. {
  86. cts = new CancellationTokenSource();
  87. DelayCloseMessageCard(millisecondTimeOut, messageCard, cts.Token);
  88. };
  89. messageWindow.Show();
  90. messageWindow.AddMessageCard(messageCard);
  91. DelayCloseMessageCard(millisecondTimeOut, messageCard, cts.Token);
  92. }
  93. /// <summary>
  94. /// 全局显示
  95. /// </summary>
  96. /// <param name="content">内容</param>
  97. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  98. /// <param name="isClearable">是否显示关闭按钮</param>
  99. public static void ShowGlobal(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  100. {
  101. ShowGlobal(MessageType.None, content, millisecondTimeOut, isClearable);
  102. }
  103. /// <summary>
  104. /// 全局显示信息
  105. /// </summary>
  106. /// <param name="content">内容</param>
  107. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  108. /// <param name="isClearable">是否显示关闭按钮</param>
  109. public static void InfoGlobal(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  110. {
  111. ShowGlobal(MessageType.Info, content, millisecondTimeOut, isClearable);
  112. }
  113. /// <summary>
  114. /// 全局显示成功
  115. /// </summary>
  116. /// <param name="content">内容</param>
  117. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  118. /// <param name="isClearable">是否显示关闭按钮</param>
  119. public static void SuccessGlobal(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  120. {
  121. ShowGlobal(MessageType.Success, content, millisecondTimeOut, isClearable);
  122. }
  123. /// <summary>
  124. /// 全局显示警告
  125. /// </summary>
  126. /// <param name="content">内容</param>
  127. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  128. /// <param name="isClearable">是否显示关闭按钮</param>
  129. public static void WarningGlobal(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  130. {
  131. ShowGlobal(MessageType.Warning, content, millisecondTimeOut, isClearable);
  132. }
  133. /// <summary>
  134. /// 全局显示错误
  135. /// </summary>
  136. /// <param name="content">内容</param>
  137. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  138. /// <param name="isClearable">是否显示关闭按钮</param>
  139. public static void ErrorGlobal(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  140. {
  141. ShowGlobal(MessageType.Error, content, millisecondTimeOut, isClearable);
  142. }
  143. #endregion 全局
  144. #region 指定容器
  145. private static void ShowInternal(MessageContainer container, MessageType type, object content, int millisecondTimeOut, bool isClearable)
  146. {
  147. container.Dispatcher.VerifyAccess();
  148. MessageCard messageCard = GetMessageCard(type, content, millisecondTimeOut, isClearable);
  149. CancellationTokenSource cts = new CancellationTokenSource();
  150. messageCard.Close += (sender, e) => container.RemoveMessageCard(messageCard);
  151. messageCard.MouseEnter += (sender, e) => cts.Cancel();
  152. messageCard.MouseLeave += (sender, e) =>
  153. {
  154. cts = new CancellationTokenSource();
  155. DelayCloseMessageCard(millisecondTimeOut, messageCard, cts.Token);
  156. };
  157. container.AddMessageCard(messageCard);
  158. DelayCloseMessageCard(millisecondTimeOut, messageCard, cts.Token);
  159. }
  160. /// <summary>
  161. /// 容器内显示
  162. /// </summary>
  163. /// <param name="containerIdentifier">容器 ID</param>
  164. /// <param name="type">类型</param>
  165. /// <param name="content">内容</param>
  166. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  167. /// <param name="isClearable">是否显示关闭按钮</param>
  168. public static void Show(string containerIdentifier, MessageType type, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  169. {
  170. if (!Containers.ContainsKey(containerIdentifier))
  171. {
  172. throw new NullReferenceException($"The message container Identifier '{containerIdentifier}' could not be found");
  173. }
  174. MessageContainer container = Containers[containerIdentifier];
  175. ShowInternal(container, type, content, millisecondTimeOut, isClearable);
  176. }
  177. /// <summary>
  178. /// 容器内显示
  179. /// (默认 Actived Window 下顶层 MessageContainer 容器)
  180. /// </summary>
  181. /// <param name="type">类型</param>
  182. /// <param name="content">内容</param>
  183. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  184. /// <param name="isClearable">是否显示关闭按钮</param>
  185. public static void Show(MessageType type, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  186. {
  187. var activedWindow = WindowHelper.GetCurrentWindow() ?? throw new NullReferenceException("Can't find the actived window");
  188. MessageContainer container = activedWindow.TryGetChildFromVisualTree<MessageContainer>(null) ?? throw new NullReferenceException("Can't Find the MessageContainer");
  189. ShowInternal(container, type, content, millisecondTimeOut, isClearable);
  190. }
  191. /// <summary>
  192. /// 容器内显示
  193. /// </summary>
  194. /// <param name="containerIdentifier">容器 ID</param>
  195. /// <param name="content">内容</param>
  196. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  197. /// <param name="isClearable">是否显示关闭按钮</param>
  198. public static void Show(string containerIdentifier, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  199. {
  200. Show(containerIdentifier, MessageType.None, content, millisecondTimeOut, isClearable);
  201. }
  202. /// <summary>
  203. /// 容器内显示
  204. /// </summary>
  205. /// <param name="content">内容</param>
  206. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  207. /// <param name="isClearable">是否显示关闭按钮</param>
  208. public static void Show(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  209. {
  210. Show(MessageType.None, content, millisecondTimeOut, isClearable);
  211. }
  212. /// <summary>
  213. /// 容器内显示信息
  214. /// </summary>
  215. /// <param name="containerIdentifier">容器 ID</param>
  216. /// <param name="content">内容</param>
  217. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  218. /// <param name="isClearable">是否显示关闭按钮</param>
  219. public static void Info(string containerIdentifier, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  220. {
  221. Show(containerIdentifier, MessageType.Info, content, millisecondTimeOut, isClearable);
  222. }
  223. /// <summary>
  224. /// 容器内显示信息
  225. /// (默认 Actived Window 下顶层 MessageContainer 容器)
  226. /// </summary>
  227. /// <param name="content">内容</param>
  228. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  229. /// <param name="isClearable">是否显示关闭按钮</param>
  230. public static void Info(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  231. {
  232. Show(MessageType.Info, content, millisecondTimeOut, isClearable);
  233. }
  234. /// <summary>
  235. /// 容器内显示成功
  236. /// </summary>
  237. /// <param name="containerIdentifier">容器 ID</param>
  238. /// <param name="content">内容</param>
  239. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  240. /// <param name="isClearable">是否显示关闭按钮</param>
  241. public static void Success(string containerIdentifier, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  242. {
  243. Show(containerIdentifier, MessageType.Success, content, millisecondTimeOut, isClearable);
  244. }
  245. /// <summary>
  246. /// 容器内显示成功
  247. /// (默认 Actived Window 下顶层 MessageContainer 容器)
  248. /// </summary>
  249. /// <param name="content">内容</param>
  250. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  251. /// <param name="isClearable">是否显示关闭按钮</param>
  252. public static void Success(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  253. {
  254. Show(MessageType.Success, content, millisecondTimeOut, isClearable);
  255. }
  256. /// <summary>
  257. /// 容器内显示警告
  258. /// </summary>
  259. /// <param name="containerIdentifier">容器 ID</param>
  260. /// <param name="content">内容</param>
  261. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  262. /// <param name="isClearable">是否显示关闭按钮</param>
  263. public static void Warning(string containerIdentifier, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  264. {
  265. Show(containerIdentifier, MessageType.Warning, content, millisecondTimeOut, isClearable);
  266. }
  267. /// <summary>
  268. /// 容器内显示警告
  269. /// (默认 Actived Window 下顶层 MessageContainer 容器)
  270. /// </summary>
  271. /// <param name="content">内容</param>
  272. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  273. /// <param name="isClearable">是否显示关闭按钮</param>
  274. public static void Warning(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  275. {
  276. Show(MessageType.Warning, content, millisecondTimeOut, isClearable);
  277. }
  278. /// <summary>
  279. /// 容器内显示错误
  280. /// </summary>
  281. /// <param name="containerIdentifier">容器 ID</param>
  282. /// <param name="content">内容</param>
  283. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  284. /// <param name="isClearable">是否显示关闭按钮</param>
  285. public static void Error(string containerIdentifier, object content, int millisecondTimeOut = 3000, bool isClearable = true)
  286. {
  287. Show(containerIdentifier, MessageType.Error, content, millisecondTimeOut, isClearable);
  288. }
  289. /// <summary>
  290. /// 容器内显示错误
  291. /// (默认 Actived Window 下顶层 MessageContainer 容器)
  292. /// </summary>
  293. /// <param name="content">内容</param>
  294. /// <param name="millisecondTimeOut">关闭延时,为 0 时不自动关闭</param>
  295. /// <param name="isClearable">是否显示关闭按钮</param>
  296. public static void Error(object content, int millisecondTimeOut = 3000, bool isClearable = true)
  297. {
  298. Show(MessageType.Error, content, millisecondTimeOut, isClearable);
  299. }
  300. #endregion 指定容器
  301. }
  302. /// <summary>
  303. /// 消息类型
  304. /// </summary>
  305. public enum MessageType
  306. {
  307. /// <summary>
  308. /// 无
  309. /// </summary>
  310. [Description("无")]
  311. None = 0,
  312. /// <summary>
  313. /// 信息
  314. /// </summary>
  315. [Description("信息")]
  316. Info,
  317. /// <summary>
  318. /// 成功
  319. /// </summary>
  320. [Description("成功")]
  321. Success,
  322. /// <summary>
  323. /// 警告
  324. /// </summary>
  325. [Description("警告")]
  326. Warning,
  327. /// <summary>
  328. /// 错误
  329. /// </summary>
  330. [Description("错误")]
  331. Error
  332. }
  333. }