using Avalonia; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using EventBus; using Shaker.Models; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; namespace ShakerApp.ViewModels; public abstract class ViewModelBase:ViewModelBase where TModel:IModel { public ViewModelBase(TModel model) : this() { UpDateModel(model); } private List AllFields = new List(); private List<(string, IReadOnlyList)> AllProperties = new List<(string, IReadOnlyList)>(); public ViewModelBase() { if (typeof(TModel).IsAnsiClass && !typeof(TModel).IsAbstract) { Model = Activator.CreateInstance(); AllFields = typeof(TModel).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList(); this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(x => x.GetCustomAttribute() != null) .ToList() .ForEach(x => { var att = x.GetCustomAttribute(); if (att == null || att.Names.Count == 0) return; AllProperties.Add((x.Name, att.Names)); }); } } [AllowNull] private TModel model = default; public virtual TModel Model { get => model; set => SetProperty(ref model, value); } public virtual void ReceiveServiceModel(TModel model) { if (typeof(TModel).IsAbstract || typeof(TModel).IsInterface) return; if (lastModel != null) { lastModel = (TModel)model.Clone(); } UpDateModel(model); } public virtual void UpDateModel(TModel model) { if (typeof(TModel).IsAbstract || typeof(TModel).IsInterface) return; List changedNames = new List(); if (model == null || AllFields.Count == 0) return; if (Model == null) { changedNames = AllFields.Select(x => x.Name).ToList(); } else { AllFields.ForEach(x => { var lastvalue = x.GetValue(Model); var fieldvalue = x.GetValue(model); if (!Object.Equals(lastvalue, fieldvalue)) { changedNames.Add(x.Name); } }); } Model = model; if (changedNames.Count == 0) return; List nochanged = new List(); changedNames.ForEach(x => { bool state = false; AllProperties.ForEach(y => { if (y.Item2.Contains(x)) { OnPropertyChanged(y.Item1); state = true; } }); if (!state) nochanged.Add(x); }); if (nochanged.Count == 0) return; RefreshUI(nochanged); } public virtual void Init() { } [AllowNull] private protected TModel lastModel; protected virtual void RefreshUI(List changedNames) { } }