using Aitex.Core.RT.Log; using Aitex.Core.UI.MVVM; using Aitex.Core.Util; using Aitex.Core.Utilities; using MECF.Framework.Common.DataCenter; using OpenSEMI.Ctrlib.Controls; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace MECF.Framework.UI.Client.ClientBase { public class UIViewModelBase : BaseModel { public string SystemName { get; set; } private PeriodicJob _timer; public bool ActiveUpdateData; protected Func _isSubscriptionAttribute; protected Func _hasSubscriptionAttribute; protected ConcurrentBag _subscribedKeys = new ConcurrentBag(); public UIViewModelBase() { _timer = new PeriodicJob(1000, OnTimer, "UIUpdateThread-" + GetType().Name); _isSubscriptionAttribute = attribute => attribute is SubscriptionAttribute; _hasSubscriptionAttribute = mi => mi.GetCustomAttributes(false).Any(_isSubscriptionAttribute); } protected override void OnActivate() { base.OnActivate(); EnableTimer(true); } protected override void OnDeactivate(bool close) { base.OnDeactivate(close); if(ActiveUpdateData) { EnableTimer(false); } } public virtual void EnableTimer(bool enable) { if (enable) { _timer.Start(); } else { _timer.Pause(); } } protected override void OnInitialize() { base.OnInitialize(); SubscribeKeys(); } protected void Subscribe(string key) { if (!string.IsNullOrEmpty(key)) { _subscribedKeys.Add(key); } } public virtual void SubscribeKeys() { SubscribeKeys(this); } public void SubscribeKeys(UIViewModelBase vm) { Parallel.ForEach(vm.GetType().GetProperties().Where(_hasSubscriptionAttribute), property => { SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (!string.IsNullOrEmpty(SystemName)) { key = $"{SystemName}.{key}"; subscription.SetModule(SystemName); } if (!_subscribedKeys.Contains(key)) { _subscribedKeys.Add(key); } }); Parallel.ForEach(vm.GetType().GetFields().Where(_hasSubscriptionAttribute), field => { SubscriptionAttribute subscription = field.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (!string.IsNullOrEmpty(SystemName)) { key = $"{SystemName}.{key}"; subscription.SetModule(SystemName); } if (!_subscribedKeys.Contains(key)) { _subscribedKeys.Add(key); } }); } protected virtual bool OnTimer() { try { Poll(); return true; } catch (Exception) { return false; } } protected virtual void Poll() { if (_subscribedKeys.Count > 0) { Dictionary data = QueryDataClient.Instance.Service.PollData(_subscribedKeys); if (data == null) { LOG.Error("获取RT数据失败"); return; } if (data.Count != _subscribedKeys.Count) { string unknowKeys = string.Empty; foreach (string key in _subscribedKeys) { if (!data.ContainsKey(key)) { unknowKeys += key + "\r\n"; } } LOG.Error("获取如下SubscribeKey数据失败" + unknowKeys); } InvokeBeforeUpdateProperty(data); UndateData(data); Application.Current?.Dispatcher.Invoke(new Action(() => { InvokePropertyChanged(); InvokeAfterUpdateProperty(data); })); } } protected virtual void InvokeBeforeUpdateProperty(Dictionary data) { } protected virtual void InvokeAfterUpdateProperty(Dictionary data) { } protected virtual void InvokePropertyChanged() { Refresh(); } private void UndateData(Dictionary data) { if (data != null) { UpdateSubscribe(data, this); } } public void UpdateSubscribe(Dictionary data, object vm) { Parallel.ForEach(vm.GetType().GetProperties().Where(_hasSubscriptionAttribute), property => { PropertyInfo pi = (PropertyInfo)property; SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = SystemName == null ? subscription.ModuleKey : $"{SystemName}.{subscription.ModuleKey}"; if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], pi.PropertyType); var originValue = Convert.ChangeType(pi.GetValue(vm, null), pi.PropertyType); if (originValue != convertedValue) { pi.SetValue(vm, convertedValue, null); } } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); Parallel.ForEach(vm.GetType().GetFields().Where(_hasSubscriptionAttribute), field => { FieldInfo fi = (FieldInfo)field; SubscriptionAttribute subscription = field.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = SystemName == null ? subscription.ModuleKey : $"{SystemName}.{subscription.ModuleKey}"; if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], fi.FieldType); var originValue = Convert.ChangeType(fi.GetValue(vm), fi.FieldType); if (originValue != convertedValue) { fi.SetValue(vm, convertedValue); } } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); } public virtual void OnWaferTransfer(DragDropEventArgs args) { try { WaferMoveManager.Instance.TransferWafer(args.TranferFrom, args.TranferTo); } catch (Exception ex) { LOG.Write(ex); } } public void OnMouseUp(object sender, MouseButtonEventArgs e) { if (e.ChangedButton != MouseButton.Right) return; if (sender is Slot slot) { ContextMenu cm = ContextMenuManager.Instance.GetSlotMenus(slot); if (cm != null) { ((FrameworkElement)e.Source).ContextMenu = cm; } return; } if (sender is CarrierContentControl carrier) { ContextMenu cm = ContextMenuManager.Instance.GetCarrierMenus(carrier); if (cm != null) { ((FrameworkElement)e.Source).ContextMenu = cm; } return; } } } }