ViewModelBase.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Threading;
  4. using CommunityToolkit.Mvvm.ComponentModel;
  5. using CommunityToolkit.Mvvm.Input;
  6. using EventBus;
  7. using Mono.CompilerServices.SymbolWriter;
  8. using Shaker.Models;
  9. using SukiUI.Dialogs;
  10. using SukiUI.Toasts;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.ComponentModel;
  14. using System.Diagnostics.CodeAnalysis;
  15. using System.IO;
  16. using System.Linq;
  17. using System.Reflection;
  18. using System.Runtime.CompilerServices;
  19. using System.Windows.Input;
  20. namespace ShakerApp.ViewModels;
  21. public abstract class ViewModelBase:ObservableObject
  22. {
  23. [return: NotNull]
  24. protected EventBus.EventBroker.EventData<TData> GetEvent<TData>() => (EventBroker.EventData<TData>)EventBroker.Instance.GetEvent<TData>();
  25. [return: NotNull]
  26. protected EventBus.EventBroker.EventData<TData, T> GetEvent<TData, T>() => (EventBroker.EventData<TData, T>)EventBroker.Instance.GetEvent<TData, T>();
  27. [return: NotNull]
  28. public EventBus.EventBroker.AnonymousEventData GetEvent([NotNull] string eventName) => (EventBroker.AnonymousEventData)EventBroker.Instance.GetEvent(eventName);
  29. [return: NotNull]
  30. public EventBus.EventBroker.AnonymousEventData<T> GetEvent<T>([NotNull] string eventName) => (EventBroker.AnonymousEventData<T>)EventBroker.Instance.GetEvent<T>(eventName);
  31. }
  32. public abstract class ViewModelBase<TModel>:ViewModelBase where TModel:IModel
  33. {
  34. public ViewModelBase(TModel model) : this()
  35. {
  36. UpDateModel(model);
  37. }
  38. private List<FieldInfo> AllFields = new List<FieldInfo>();
  39. private List<(string, IReadOnlyList<string>)> AllProperties = new List<(string, IReadOnlyList<string>)>();
  40. public ViewModelBase()
  41. {
  42. if (typeof(TModel).IsAnsiClass && !typeof(TModel).IsAbstract)
  43. {
  44. Model = Activator.CreateInstance<TModel>();
  45. AllFields = typeof(TModel).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
  46. this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
  47. .Where(x => x.GetCustomAttribute<ViewModels.PropertyAssociationAttribute>() != null)
  48. .ToList()
  49. .ForEach(x =>
  50. {
  51. var att = x.GetCustomAttribute<PropertyAssociationAttribute>();
  52. if (att == null || att.Names.Count == 0) return;
  53. AllProperties.Add((x.Name, att.Names));
  54. });
  55. }
  56. }
  57. [AllowNull]
  58. private TModel model = default;
  59. public virtual TModel Model { get => model; set => SetProperty(ref model, value); }
  60. public virtual void ReceiveServiceModel(TModel model)
  61. {
  62. if (typeof(TModel).IsAbstract || typeof(TModel).IsInterface) return;
  63. if (lastModel != null)
  64. {
  65. lastModel = (TModel)model.Clone();
  66. }
  67. UpDateModel(model);
  68. }
  69. public virtual void UpDateModel(TModel model)
  70. {
  71. if (typeof(TModel).IsAbstract || typeof(TModel).IsInterface) return;
  72. List<string> changedNames = new List<string>();
  73. if (model == null || AllFields.Count == 0) return;
  74. if (Model == null)
  75. {
  76. changedNames = AllFields.Select(x => x.Name).ToList();
  77. }
  78. else
  79. {
  80. AllFields.ForEach(x =>
  81. {
  82. var lastvalue = x.GetValue(Model);
  83. var fieldvalue = x.GetValue(model);
  84. if (!Object.Equals(lastvalue, fieldvalue))
  85. {
  86. changedNames.Add(x.Name);
  87. }
  88. });
  89. }
  90. Model = model;
  91. if (changedNames.Count == 0) return;
  92. List<string> nochanged = new List<string>();
  93. changedNames.ForEach(x =>
  94. {
  95. bool state = false;
  96. AllProperties.ForEach(y =>
  97. {
  98. if (y.Item2.Contains(x))
  99. {
  100. OnPropertyChanged(y.Item1);
  101. state = true;
  102. }
  103. });
  104. if (!state) nochanged.Add(x);
  105. });
  106. if (nochanged.Count == 0) return;
  107. RefreshUI(nochanged);
  108. }
  109. public virtual void Init()
  110. {
  111. }
  112. [AllowNull]
  113. private protected TModel lastModel;
  114. protected virtual void RefreshUI(List<string> changedNames)
  115. {
  116. }
  117. }
  118. public abstract class DisplayViewModelBase<TModel> : ViewModelBase<TModel> where TModel : IModel
  119. {
  120. public DisplayViewModelBase() : base() { }
  121. public DisplayViewModelBase(TModel model):base(model) { }
  122. private string Caption => (string)(App.Current?.FindResource("PromptTitle") ?? "");
  123. private string Yes => (string)(App.Current?.FindResource("PromptYes") ?? "");
  124. private string No => (string)(App.Current?.FindResource("PromptNo") ?? "");
  125. public virtual double Width => double.NaN;
  126. public virtual double Height => double.NaN;
  127. public virtual bool CanResize => true;
  128. [AllowNull]
  129. public Action CloseWindowAction { get; set; }
  130. public ISukiToastManager ToastManager { get; } = new SukiToastManager();
  131. public ISukiDialogManager DialogManager { get; } = new SukiDialogManager();
  132. [AllowNull]
  133. public virtual Type Content
  134. {
  135. get => content;
  136. set => SetProperty(ref content , value);
  137. }
  138. private string title = string.Empty;
  139. private bool saveIsEnabled= false;
  140. public bool SaveIsEnabled
  141. {
  142. get { return saveIsEnabled; }
  143. set {SetProperty(ref saveIsEnabled , value); }
  144. }
  145. [AllowNull]
  146. public virtual bool CanCancel { get; } = typeof(TModel).IsAnsiClass && !typeof(TModel).IsAbstract;
  147. public bool ShowError(string msg)
  148. {
  149. return Tools.DispatherInovke.Inovke(()=> DialogManager.CreateDialog()
  150. .OfType(Avalonia.Controls.Notifications.NotificationType.Error)
  151. .WithTitle(Caption)
  152. .WithContent(msg)
  153. .WithActionButton
  154. (Yes, _ => { }, true).TryShow());
  155. }
  156. public bool ShowAsk(string msg, Action? yesaction = null, Action? noaction = null)
  157. {
  158. return Tools.DispatherInovke.Inovke(()=> DialogManager.CreateDialog()
  159. .OfType(Avalonia.Controls.Notifications.NotificationType.Information)
  160. .WithTitle(Caption)
  161. .WithContent(msg)
  162. .WithActionButton(Yes, _ => yesaction?.Invoke(), true)
  163. .WithActionButton(No, _ => noaction?.Invoke(), true)
  164. .TryShow());
  165. }
  166. public bool ShowInfo(string msg)
  167. {
  168. return Tools.DispatherInovke.Inovke(()=> DialogManager.CreateDialog()
  169. .OfType(Avalonia.Controls.Notifications.NotificationType.Information)
  170. .WithTitle(Caption)
  171. .WithContent(msg)
  172. .WithActionButton
  173. (Yes, _ => { }, true).TryShow());
  174. }
  175. public bool ShowSuccess(string msg)
  176. {
  177. return Tools.DispatherInovke.Inovke(()=> DialogManager.CreateDialog()
  178. .OfType(Avalonia.Controls.Notifications.NotificationType.Success)
  179. .WithTitle(Caption)
  180. .WithContent(msg)
  181. .WithActionButton
  182. (Yes, _ => { }, true).TryShow());
  183. }
  184. public bool ShowWarning(string msg)
  185. {
  186. return Tools.DispatherInovke.Inovke(()=> DialogManager.CreateDialog()
  187. .OfType(Avalonia.Controls.Notifications.NotificationType.Warning)
  188. .WithTitle(Caption)
  189. .WithContent(msg)
  190. .WithActionButton
  191. (Yes, _ => { }, true).TryShow());
  192. }
  193. public void ShowToast(string msg,Avalonia.Controls.Notifications.NotificationType type = Avalonia.Controls.Notifications.NotificationType.Information)
  194. {
  195. if (ToastManager == null) return;
  196. Tools.DispatherInovke.Inovke(()=> ToastManager.CreateToast()
  197. .WithTitle(Caption)
  198. .WithContent(msg)
  199. .OfType(type)
  200. .Dismiss().After(TimeSpan.FromSeconds(3))
  201. .Dismiss().ByClicking()
  202. .Queue());
  203. }
  204. private bool cansave = false;
  205. public virtual string OKContent => "Save";
  206. public virtual string CancelContent =>"Cancel";
  207. public ICommand SaveCommand => new RelayCommand(()=>
  208. {
  209. if (!cansave) return;
  210. Save();
  211. cansave = false;
  212. });
  213. public ICommand CancelCommand => new RelayCommand(Cancel);
  214. public virtual string Title { get => title; set =>SetProperty(ref title , value); }
  215. public bool ButtonVisibily { get => buttonVisibily; set =>SetProperty(ref buttonVisibily , value); }
  216. protected virtual void Save()
  217. {
  218. lastModel = default;
  219. }
  220. [AllowNull]
  221. private Type content;
  222. public virtual void InitData()
  223. {
  224. cansave = true;
  225. if (CanCancel)
  226. {
  227. lastModel = (TModel)Model.Clone();
  228. SaveIsEnabled = false;
  229. }
  230. else
  231. {
  232. //lastModel = default;
  233. }
  234. }
  235. protected virtual bool SkipProperty(string? propertyName)
  236. {
  237. return false;
  238. }
  239. protected override void OnPropertyChanged(PropertyChangedEventArgs e)
  240. {
  241. base.OnPropertyChanged(e);
  242. if (e.PropertyName == nameof(Content)
  243. || e.PropertyName == nameof(Model)
  244. || e.PropertyName == nameof(ButtonVisibily)
  245. || e.PropertyName == nameof(SaveCommand)
  246. || e.PropertyName == nameof(Title)
  247. || e.PropertyName == nameof(SaveIsEnabled)
  248. || e.PropertyName == nameof(CancelCommand))
  249. return;
  250. if (SkipProperty(e.PropertyName)) return;
  251. SaveIsEnabled = true;
  252. }
  253. private bool buttonVisibily = true;
  254. protected virtual void Cancel()
  255. {
  256. if (CanCancel && lastModel !=null)
  257. {
  258. UpDateModel(lastModel);
  259. lastModel = default;
  260. }
  261. }
  262. }