jiangjy пре 2 месеци
родитељ
комит
a133f0cd08

+ 3 - 0
FrameworkLocal/Common/DataCenter/IQueryDataService.cs

@@ -285,5 +285,8 @@ namespace MECF.Framework.Common.DataCenter
 
         [OperationContract]
         bool ClearByRecipePathHistory(string RecipePath);
+
+        [OperationContract]
+        string GetFileXmlContent(string fileName, string diretory = "GasXml");
     }
 }

+ 4 - 1
FrameworkLocal/Common/DataCenter/QueryDataService.cs

@@ -328,7 +328,10 @@ namespace MECF.Framework.Common.DataCenter
         {
             return RecipeEditHistoryRecorder.QueryByRecipePathHistory(RecipePath, 20);
         }
-
+        public string GetFileXmlContent(string fileName, string diretory)
+        {
+            return Singleton<ConfigManager>.Instance.GetXmlContent(fileName, diretory); ;
+        }
         public bool ClearByRecipePathHistory(string RecipePath)
         {
             return RecipeEditHistoryRecorder.ClearByRecipePathHistory(RecipePath);

+ 7 - 0
FrameworkLocal/Common/DataCenter/QueryDataServiceClient.cs

@@ -378,5 +378,12 @@ namespace MECF.Framework.Common.DataCenter
             Invoke(svc => { result = svc.ClearByRecipePathHistory(RecipePath); });
             return result;
         }
+
+        public string GetFileXmlContent(string fileName, string diretory)
+        {
+            string result = string.Empty;
+            Invoke(svc => { result = svc.GetFileXmlContent(fileName, diretory); });
+            return result;
+        }
     }
 }

+ 7 - 0
FrameworkLocal/Common/SCCore/ConfigManager.cs

@@ -10,6 +10,7 @@ using System.Collections.Concurrent;
 using Aitex.Core.RT.DataCenter;
 using Aitex.Core.RT.OperationCenter;
 using Aitex.Core.Util;
+using MECF.Framework.Common.Utilities;
 
 namespace Aitex.Core.RT.ConfigCenter
 {
@@ -206,5 +207,11 @@ namespace Aitex.Core.RT.ConfigCenter
 
             return result;
         }
+
+        public string GetXmlContent(string fileName, string diretory)
+        {
+            var filePath = PathManager.GetCfgDir() + $"{diretory}\\" + fileName;
+            return FileHelper.Instance.ReadFileStream(filePath);
+        }
     }
 }

+ 21 - 0
FrameworkLocal/UIClient/ClientBase/UIViewModelBase.cs

@@ -18,6 +18,7 @@ using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
+using System.Xml.Linq;
 
 namespace MECF.Framework.UI.Client.ClientBase
 {
@@ -301,7 +302,27 @@ namespace MECF.Framework.UI.Client.ClientBase
             _hasSubscriptionAttribute = mi => mi.GetCustomAttributes(false).Any(_isSubscriptionAttribute);
         }
 
+        public Dictionary<string, Dictionary<string, string>> GetDevice(string deviceType, string deviceName, XDocument xmlDoc, string filterStr = "id")
+        {
+            if (string.IsNullOrEmpty(deviceType)) return default;
+
+            Dictionary<string, Dictionary<string, string>> result = new Dictionary<string, Dictionary<string, string>>();
 
+            var ioLpNodes = xmlDoc.Descendants(deviceType);
+            foreach (var ioLpNode in ioLpNodes)
+            {
+                if (ioLpNode.Attribute(filterStr).Value != deviceName) continue;
+
+                Dictionary<string, string> attributes = new Dictionary<string, string>();
+                foreach (XAttribute attribute in ioLpNode.Attributes())
+                {
+                    attributes[attribute.Name.LocalName] = attribute.Value;
+                }
+
+                result.Add(ioLpNode.Attribute(filterStr).Value, attributes);
+            }
+            return result;
+        }
         //
         protected virtual bool OnTimer()
         {

+ 1 - 0
Furnace/FurnaceRT/Config/FurnaceGemModel.xml

@@ -2352,6 +2352,7 @@
     <ECID id="10010038" valueType="Ascii" logicalName="System.N2PurgeData" value="" min="" max="" eventTrigger="" units="" description="N2PurgeData" isArray="false" />
     <ECID id="10010039" valueType="Ascii" logicalName="System.N2ToAirData" value="" min="" max="" eventTrigger="" units="" description="N2ToAirData" isArray="false" />
     <ECID id="10010040" valueType="Ascii" logicalName="System.ZIPToDesktop" value="" min="" max="" eventTrigger="" units="" description="ZIP To Desktop" isArray="false" />
+    <ECID id="10010041" valueType="Ascii" logicalName="System.AxisMonShowKey" value="" min="" max="" eventTrigger="" units="" description="" isArray="false" />
     <ECID id="10020001" valueType="Ascii" logicalName="System.EditParameter.EditChamberType" value="" min="" max="" eventTrigger="" units="" description="Edit Chamber Type" isArray="false" />
     <ECID id="10020002" valueType="Ascii" logicalName="System.EditParameter.EditParameterType" value="" min="" max="" eventTrigger="" units="" description="Alarm Condition,Temp Correction,Temp PID,Temp Profile,Temp Auto PID,Leak Check Condition,APC PID" isArray="false" />
     <ECID id="10030001" valueType="Ascii" logicalName="System.FDC.DataGroupName" value="" min="" max="" eventTrigger="" units="" description="FDC data group" isArray="false" />

+ 10 - 1
Furnace/FurnaceRT/Config/IO/ELK/DeviceModelPM.xml

@@ -264,6 +264,11 @@
 	</IoBufferMotors>
 	<IoFurnaceMotors assembly="FurnaceRT" classType="FurnaceRT.Devices.IoFurnaceMotor">
 		<IoFurnaceMotor id="BoatElevatorServo" display="" schematicId="" unit="" module=""
+						diVAC1="DI_VAC1"
+						diVAC2="DI_VAC2"
+						diVAC3="DI_VAC3"
+						diBoatUnloadInterlock="DI_BoatUnloadInterlock"
+						
 						diMove=""
 						diServoOn="DI_PwrBusyBoatZAxis"
 						diPowerOnError=""
@@ -458,7 +463,11 @@
 					scRootPath=""
 	    />
 	</IoCarrierRobots>
-
+	
+	<IoStockers classType="FurnaceRT.Devices.IoStocker" assembly="FurnaceRT">
+		<IoStocker id="Stocker17"  display="EX1" schematicId="Stocker17" unit=""		  doValExtend=""		  doValBack=""			  doFlowOpen=""   diBackDetect=""		  diExtendedDetect=""		  diFlowDetect1=""		  diFlowDetect2=""		  diInPosition1="DI_LAFrontFOUPBuffer1InPosition"	  aioType="float"/>
+		<IoStocker id="Stocker18"  display="EX2" schematicId="Stocker18" unit=""		  doValExtend=""		  doValBack=""		      doFlowOpen=""  diBackDetect=""	  diExtendedDetect=""		  diFlowDetect1=""	  diFlowDetect2=""	  diInPosition1="DI_LAFrontFOUPBuffer2InPosition"	  aioType="float"/>
+	</IoStockers>
 	<!--<IoRFs classType="FurnaceRT.Devices.IoRF" assembly="FurnaceRT">
 		<IoRF id="RF" display="RF" schematicId="RF" unit=""
 					aiRelfectionPower="AI_RFGeneratorRelfectionPower"

+ 1 - 0
Furnace/FurnaceRT/Config/System.sccfg

@@ -8,6 +8,7 @@
 		<config default="false" name="IsShowRobotDownBtn" description="" max="" min="" paramter="" tag="" unit="" type="Bool"  visible="false"  />
 		<config default="true" name="IsATMMode" description="Is ATM Mode" max="" min="" paramter="" tag="" unit="" type="Bool" visible="false"  />
 		<config default="false" name="IsCycleMode" description="Is Cycle Mode" max="" min="" paramter="" tag="" unit="" type="Bool" />
+		<config default="false" name="AxisMonShowKey" description="" max="" min="" paramter="" tag="" unit="" type="Bool" visible="false" />
 		<config default="3" name="CycleCount" description="Cycle Count" max="999999" min="1" paramter="" tag="" unit="" type="Integer" />
 		<config default="true" name="EnableWarningWaferProcessState" description="Enable Warning Wafer Process State" max="" min="" paramter="" tag="" unit="" type="Bool" />
 		<config default="true" name="EnableWarningFailedWafer" description="Enable Warning Failed Wafer" max="" min="" paramter="" tag="" unit="" type="Bool" />

BIN
Furnace/FurnaceRT/Config/VIDs/Equipment_VIDs_20250604.xlsx


Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
Furnace/FurnaceRT/Config/VIDs/_ECID.xml


+ 2 - 0
Furnace/FurnaceRT/Devices/DeviceStatus.cs

@@ -30,5 +30,7 @@ namespace FurnaceRT.Devices
         Clamp,
         On,
         Off,
+
+   
     }
 }

+ 4 - 4
Furnace/FurnaceRT/Devices/IoFIMS.cs

@@ -164,20 +164,20 @@ namespace FurnaceRT.Devices
                 if (_diFOUPVacuumSuckingOK != null && !_diFOUPVacuumSuckingOK.Value
                   &&
                   _diFOUPVacuumSuckingNotOK != null && _diFOUPVacuumSuckingNotOK.Value)
-                    return DeviceStatus.Open;
+                    return DeviceStatus.On;
 
                 if (_diFOUPVacuumSuckingOK != null && _diFOUPVacuumSuckingOK.Value
                     &&
                     _diFOUPVacuumSuckingNotOK != null && !_diFOUPVacuumSuckingNotOK.Value)
-                    return DeviceStatus.Close;
+                    return DeviceStatus.Off;
 
                 if (_doVaccumValveOpen != null && _doVaccumValveClose != null &&
                     _doVaccumValveOpen.Value && !_doVaccumValveClose.Value)
-                    return DeviceStatus.Open;
+                    return DeviceStatus.On;
 
                 if (_doVaccumValveOpen != null && _doVaccumValveClose != null &&
                     !_doVaccumValveOpen.Value && _doVaccumValveClose.Value)
-                    return DeviceStatus.Close;
+                    return DeviceStatus.Off;
 
                 return DeviceStatus.Unknown;
             }

+ 2 - 2
Furnace/FurnaceUI/Views/Maintenances/FIMSRobotView.xaml

@@ -249,7 +249,7 @@
                     <TextBlock Text="{Binding FIMS1VaccumValveOpenCloseStatus}" TextWrapping="Wrap" Foreground="{DynamicResource FG_Black}" FontSize="16" FontFamily="Arial" VerticalAlignment="Center"/>
                 </Border>
                 <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0 0 1 1" Background="{DynamicResource Table_BG_Content}" Grid.Row="7" Grid.Column="2" Padding="5,1">
-                    <Button  Content="Open"  Foreground="{DynamicResource FG_Black}" FontSize="16" Height="37" FontFamily="Arial" VerticalAlignment="Center">
+                    <Button  Content="On"  Foreground="{DynamicResource FG_Black}" FontSize="16" Height="37" FontFamily="Arial" VerticalAlignment="Center">
                         <i:Interaction.Triggers>
                             <i:EventTrigger EventName="Click">
                                 <cal:ActionMessage MethodName="SetVaccumValveOpen">
@@ -261,7 +261,7 @@
                     </Button>
                 </Border>
                 <Border BorderBrush="{DynamicResource Table_BD}" BorderThickness="0 0 1 1" Background="{DynamicResource Table_BG_Content}" Grid.Row="7" Grid.Column="3" Padding="5,1">
-                    <Button  Content="Close"  Foreground="{DynamicResource FG_Black}" FontSize="16" Height="37" FontFamily="Arial" VerticalAlignment="Center">
+                    <Button  Content="Off"  Foreground="{DynamicResource FG_Black}" FontSize="16" Height="37" FontFamily="Arial" VerticalAlignment="Center">
                         <i:Interaction.Triggers>
                             <i:EventTrigger EventName="Click">
                                 <cal:ActionMessage MethodName="SetVaccumValveOpen">

Разлика између датотеке није приказан због своје велике величине
+ 925 - 830
Furnace/FurnaceUI/Views/Maintenances/IOListEditView.xaml


+ 286 - 179
Furnace/FurnaceUI/Views/Maintenances/IOListEditViewModel.cs

@@ -1,12 +1,16 @@
-using Aitex.Core.RT.IOCore;
-using Aitex.Core.RT.SCCore;
-using DocumentFormat.OpenXml.Office2010.Excel;
-using MECF.Framework.Common.Config;
+using Aitex.Common.Util;
+using Aitex.Core.RT.IOCore;
+using Aitex.Core.Util;
+using DocumentFormat.OpenXml.Wordprocessing;
+using FurnaceUI.Views.Recipes;
 using MECF.Framework.Common.DataCenter;
+using MECF.Framework.Common.Equipment;
 using MECF.Framework.Common.IOCore;
 using MECF.Framework.Common.OperationCenter;
+using MECF.Framework.Common.Utilities;
 using MECF.Framework.UI.Client.ClientBase;
 using OpenSEMI.ClientBase.IO;
+using SciChart.Core.Extensions;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -17,6 +21,7 @@ using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
+using System.Xml.Linq;
 
 namespace FurnaceUI.Views.Maintenances
 {
@@ -26,18 +31,29 @@ namespace FurnaceUI.Views.Maintenances
     /// </summary>
     public class IOListEditViewModel : UiViewModelBase
     {
+        private XDocument xmlDoc = new XDocument();
+
         public ObservableCollection<IOItem<bool>> DIs { get; private set; }
         public ObservableCollection<IOItem<bool>> DOs { get; private set; }
-        private PMDeviceConfig _deviceConfig;
+        public ObservableCollection<IOItem<float>> AIs { get; private set; }
+        public ObservableCollection<AOItemFloat> AOs { get; private set; }
+        private bool _dIDOVisibility = true;
+        public bool DIDOVisibility { get => _dIDOVisibility; set => SetField(ref _dIDOVisibility, value, nameof(DIDOVisibility)); }
+        private bool _aIAOVisibility = true;
+        public bool AIAOVisibility { get => _aIAOVisibility; set => SetField(ref _aIAOVisibility, value, nameof(AIAOVisibility)); }
+        private int _selectedIndexData = 0;
+        public int SelectedIndexData { get => _selectedIndexData; set => SetField(ref _selectedIndexData, value, nameof(SelectedIndexData)); }
         private string _diKey;
         private string _doKey;
+        private string _aiKey;
+        private string _aoKey;
         #region 构造函数
         /// <summary>
         /// 构造函数
         /// </summary>
         public IOListEditViewModel()
         {
-            
+
         }
         #endregion
 
@@ -46,35 +62,25 @@ namespace FurnaceUI.Views.Maintenances
         /// 系统名称
         /// </summary>
         public string SystemName { get; set; }
+        public string TypeName { get; set; }
+        private string _deviceName;
+        public string DeviceName { get => _deviceName; set => SetField(ref _deviceName, value, nameof(DeviceName)); }
+
+
         #endregion
 
         #region 属性 
 
+        public ListCollectionView AIViewSource { get; set; }
+        public ListCollectionView AOViewSource { get; set; }
         public ListCollectionView INViewSource { get; set; }
 
         public ListCollectionView OutViewSource { get; set; }
 
         public ListCollectionView BufferViewSource { get; set; }
-        public bool IsPermission { get => this.Permission == 3; }
-        private string _id;
-
-        private string _displayId;
-
-        public string DisplayID
-        {
-            get { return _displayId; }
-            set
-            {
-                if (_displayId != value)
-                {
-                    _displayId = value;
-                    NotifyOfPropertyChange("DisplayID");
-                }
-            }
-        }
-
-
 
+        private bool _isSimulatorMode;
+        private bool _showKey;
         #endregion
 
         #region 重写方法 初始化
@@ -84,28 +90,38 @@ namespace FurnaceUI.Views.Maintenances
         protected override void OnInitialize()
         {
             base.OnInitialize();
+            string toolType = (string)QueryDataClient.Instance.Service.GetConfig("System.SetUp.ToolType");
+            _showKey = (bool)QueryDataClient.Instance.Service.GetConfig("System.AxisMonShowKey");
+            var xmlContent = QueryDataClient.Instance.Service.GetFileXmlContent("DeviceModelPM.xml", $"IO\\{toolType}");
+            xmlDoc = XDocument.Parse(xmlContent);
+
+            _isSimulatorMode = (bool)QueryDataClient.Instance.Service.GetConfig($"System.IsSimulatorMode");
+
             _diKey = $"{SystemName}.DIItemList";
             _doKey = $"{SystemName}.DOItemList";
+            _aiKey = $"{SystemName}.AIItemList";
+            _aoKey = $"{SystemName}.AOItemList";
+
+            this.AIs = InitIOData<float>(IOType.AI, _aiKey);
+            this.AOs = InitIOData(IOType.AO, _aoKey);
             this.DIs = InitIOData<bool>(IOType.DI, _diKey);
             this.DOs = InitIOData<bool>(IOType.DO, _doKey);
+
+
             _diKey = $"{SystemName}.DIList";
             _doKey = $"{SystemName}.DOList";
+            _aiKey = $"{SystemName}.AIList";
+            _aoKey = $"{SystemName}.AOList";
+            Subscribe(_aiKey);
+            Subscribe(_aoKey);
             Subscribe(_diKey);
             Subscribe(_doKey);
-            var type = QueryDataClient.Instance.Service.GetConfig("System.SetUp.ToolType");
-            if (type != null)
-            {
-                var xmlContent = QueryDataClient.Instance.Service.GetFileContent($"Config\\IO\\{type}\\DeviceModelPM.xml");
-                _deviceConfig = XmlSerializerExtension.Read<PMDeviceConfig>(xmlContent);
-            }
-            if (DisplayName.StartsWith("Load Port")) 
-            {
-                _id = "LP" + DisplayName.Substring(10);
-                DisplayID = "LP " + DisplayName.Substring(10); 
-            }
         }
         #endregion
 
+
+
+
         #region 重新方法 激活
         /// <summary>
         /// 激活
@@ -114,10 +130,39 @@ namespace FurnaceUI.Views.Maintenances
         {
             base.OnActivate();
             FilterData();
+
         }
         #endregion
 
         #region 重写方法 InitIOData
+        public ObservableCollection<AOItemFloat> InitIOData(IOType type, string dataName)
+        {
+            //get the whole informations
+            ObservableCollection<AOItemFloat> da = new ObservableCollection<AOItemFloat>();
+
+            if (type == IOType.AO)
+            {
+                var diList = QueryDataClient.Instance.Service.GetData(dataName);
+
+                if (diList != null)
+                {
+                    List<NotifiableIoItem> item = (List<NotifiableIoItem>)diList;
+                    for (int i = 0; i < item.Count; i++)
+                    {
+                        da.Add(new AOItemFloat()
+                        {
+                            Index = da.Count,
+                            Name = item[i].Name,
+                            //DisplayName = item[i].Name.Substring(item[i].Name.IndexOf('.') + 1),
+                            DisplayName = item[i].Name,
+                            Value = item[i].FloatValue,
+                            Address = item[i].Address
+                        });
+                    }
+                }
+            }
+            return da;
+        }
         /// <summary>
         /// InitIOData
         /// </summary>
@@ -179,87 +224,101 @@ namespace FurnaceUI.Views.Maintenances
                     }
                 }
             }
+
+            if (type == IOType.AI)
+            {
+                var diList = QueryDataClient.Instance.Service.GetData(dataName);
+
+                if (diList != null)
+                {
+                    List<NotifiableIoItem> item = (List<NotifiableIoItem>)diList;
+                    for (int i = 0; i < item.Count; i++)
+                    {
+                        da.Add(new IOItem<T>()
+                        {
+                            Index = da.Count,
+                            Name = item[i].Name,
+                            //DisplayName = item[i].Name.Substring(item[i].Name.IndexOf('.') + 1),
+                            DisplayName = item[i].Name,
+                            Value = (T)(object)item[i].FloatValue,
+                            Address = item[i].Address
+                        });
+
+                    }
+                }
+            }
+
             return da;
         }
         #endregion
 
         #region 方法 筛选数据显示
+        private Dictionary<string, string> GetDiDoAiAo()
+        {
+            Dictionary<string, string> resultDict = new Dictionary<string, string>();
+            List<string> result = new List<string>();
+
+            foreach (var item in DeviceName.Split(','))
+            {
+                var deviceNames = GetDevice(TypeName, item, xmlDoc);
+                if (deviceNames.Count == 0)
+                {
+                    continue;
+                }
+
+                foreach (var nodeItem in deviceNames[item])
+                {
+                    if (!string.IsNullOrEmpty(nodeItem.Value) && nodeItem.Value.Contains("_"))
+                    {
+                        //var keyStr = nodeItem.Key;
+                        //if (nodeItem.Key.StartsWith("di"))
+                        //{
+                        //    keyStr = "di";
+                        //}
+                        //else if (nodeItem.Key.StartsWith("do"))
+                        //{
+                        //    keyStr = "do";
+                        //}
+                        //else if (nodeItem.Key.StartsWith("ai"))
+                        //{
+                        //    keyStr = "ai";
+                        //}
+                        //else if (nodeItem.Key.StartsWith("ao"))
+                        //{
+                        //    keyStr = "ao";
+                        //}
+                        resultDict.Add(nodeItem.Key, nodeItem.Value);
+                    }
+                }
+            }
+
+            return resultDict;
+        }
         /// <summary>
         /// 筛选数据显示
         /// </summary>
         private void FilterData()
         {
+
+
+            var diDoAiAoData = GetDiDoAiAo();
+            AIViewSource = new ListCollectionView(AIs);
             INViewSource = new ListCollectionView(DIs);
             BufferViewSource = new ListCollectionView(DIs);
+
             INViewSource.Filter = (object obi) =>
             {
                 bool isfilter = false;
                 if (obi is IOItem item)
                 {
-                    switch (DisplayName)
+                    var fileterName = _isSimulatorMode ? item.Name.Replace("PM1.", "") : item.Name;
+                    if (diDoAiAoData != null && diDoAiAoData.Count > 0 && diDoAiAoData.Values.Contains(fileterName))
                     {
-                        case "Load Port 1":
-                            //if (item.Index <= 1863 && item.Index >= 1856)
-                            //{
-                            //    isfilter = true;
-                            //}
-                            //break;
-                        case "Load Port 2":
-                            //if (item.Index <= 1879 && item.Index >= 1872)
-                            //{
-                            //    isfilter = true;
-                            //}
-                            //break;
-                        case "Load Port 3":                     
-                        case "Load Port 4":
-                            if (_deviceConfig != null)
-                            {
-                                var lp = _deviceConfig.IoLPs.IoLP.Find(r => r.SchematicId == _id);
-                                var name = item.Name.Replace("PM1.", "");
-                                if (lp.DiDetect== name || lp.DiInPosition2== name || lp.DiInPosition1== name || lp.DiInPosition3 == name
-                                || lp.DiLeftClamp== name || lp.DiLeftRelease== name || lp.DiRightClamp== name || lp.DiRightRelease== name)
-                                    isfilter = true;
-                            }
-                            break;
-                        case "Fims 1":
-                            if (item.Index <= 1822 && item.Index >= 1808)
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Fims 2":
-                            if (item.Index <= 1838 && item.Index >= 1824)
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Buffer":
-                            if (BufferViews.Contains(item.Name.Split('.').LastOrDefault()))
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Boat":
-                            if ((item.Index <= 1307 && item.Index >= 1306) || (item.Index <= 1771 && item.Index >= 1768) || (item.Index <= 3275 && item.Index >= 3274) || (item.Index <= 3204 && item.Index >= 3201) || (item.Index <= 1296 && item.Index >= 1296) || item.Address == "D81.10")
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Wafer Robot":
-                            if (item.Index <= 1849 && item.Index >= 1845)
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Carrier Loader":
-                            if ((item.Index <= 1914 && item.Index >= 1911) || (item.Index <= 1899 && item.Index >= 1898))
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        default:
-                            break;
+                        var pmContentItem = diDoAiAoData.FirstOrDefault(a => a.Value.Equals(fileterName));
+                        item.DisplayName = _showKey ? pmContentItem.Key : pmContentItem.Value;
+                        isfilter = true;
                     }
+            
                 }
                 return isfilter;
             };
@@ -268,85 +327,87 @@ namespace FurnaceUI.Views.Maintenances
                 bool isfilter = false;
                 if (obi is IOItem item)
                 {
-                    if (DisplayName == "Buffer")
+                    var fileterName = _isSimulatorMode ? item.Name.Replace("PM1.", "") : item.Name;
+                    if (diDoAiAoData != null && diDoAiAoData.Count > 0 && diDoAiAoData.Values.Contains(fileterName))
                     {
-                        if (item.Index == 1792)
-                        {
-                            isfilter = true;
-                        }
+                        var pmContentItem = diDoAiAoData.FirstOrDefault(a => a.Value.Equals(fileterName));
+                        item.DisplayName = _showKey ? pmContentItem.Key : pmContentItem.Value;
+                        isfilter = true;
+                    }
+                    //if (DisplayName == "Buffer")
+                    //{
+                    //    if (item.Index == 1792)
+                    //    {
+                    //        isfilter = true;
+                    //    }
+                    //}
+                }
+                return isfilter;
+            };
+
+            AIViewSource.Filter = (object obi) =>
+            {
+                bool isfilter = false;
+                if (obi is IOItem item)
+                {
+                    var fileterName = _isSimulatorMode ? item.Name.Replace("PM1.", "") : item.Name;
+                    if (diDoAiAoData != null && diDoAiAoData.Count > 0 && diDoAiAoData.Values.Contains(fileterName))
+                    {
+                        var pmContentItem = diDoAiAoData.FirstOrDefault(a => a.Value.Equals(fileterName));
+                        item.DisplayName = _showKey ? pmContentItem.Key : pmContentItem.Value;
+                        isfilter = true;
                     }
                 }
                 return isfilter;
             };
 
             OutViewSource = new ListCollectionView(DOs);
+            AOViewSource = new ListCollectionView(AOs);
+            AOViewSource.Filter = (object obi) =>
+            {
+                bool isfilter = false;
+                if (obi is IOItem item)
+                {
+                    var fileterName = _isSimulatorMode ? item.Name.Replace("PM1.", "") : item.Name;
+                    if (diDoAiAoData != null && diDoAiAoData.Count > 0 && diDoAiAoData.Values.Contains(fileterName))
+                    {
+                        var pmContentItem = diDoAiAoData.FirstOrDefault(a => a.Value.Equals(fileterName));
+                        item.DisplayName = _showKey ? pmContentItem.Key : pmContentItem.Value;
+                        isfilter = true;
+                    }
 
+                }
+                return isfilter;
+            };
             OutViewSource.Filter = (object obi) =>
             {
                 bool isfilter = false;
                 if (obi is IOItem item)
                 {
-                    switch (DisplayName)
+                    var fileterName = _isSimulatorMode ? item.Name.Replace("PM1.", "") : item.Name;
+                    if (diDoAiAoData != null && diDoAiAoData.Count > 0 && diDoAiAoData.Values.Contains(fileterName))
                     {
-                        case "Load Port 1":
-                            //if ((item.Index <= 215 && item.Index >= 214) || (item.Index <= 224 && item.Index >= 220))
-                            //{
-                            //    isfilter = true;
-                            //}
-                            //break;
-                        case "Load Port 2":
-                            //if (item.Index <= 234 && item.Index >= 228)
-                            //{
-                            //    isfilter = true;
-                            //}
-                            //break;
-                        case "Load Port 3":
-                        case "Load Port 4":
-                            if (_deviceConfig != null)
-                            {
-                                var lp = _deviceConfig.IoLPs.IoLP.Find(r => r.SchematicId == _id);
-                                var name = item.Name.Replace("PM1.","");
-                                if (lp.DoManual == name || lp.DoLoad == name || lp.DoPresence == name || lp.DoClamp == name
-                                || lp.DoUnload == name || lp.DoPlacement == name || lp.DoRelease == name)
-                                    isfilter = true;
-                            }
-                            break;
-                        case "Fims 1":
-                            if (item.Index <= 373 && item.Index >= 370)
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Fims 2":
-                            if (item.Index <= 377 && item.Index >= 374)
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Buffer":
-                            break;
-                        case "Boat":
-                            if (item.Address == "D1088.14"
-                              || item.Address == "D1088.15")
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        case "Wafer Robot":
-                            break;
-                        case "Carrier Loader":
-                            if (item.Address == "D1092.8"
-                              || item.Address == "D1092.9")
-                            {
-                                isfilter = true;
-                            }
-                            break;
-                        default:
-                            break;
+                        var pmContentItem = diDoAiAoData.FirstOrDefault(a => a.Value.Equals(fileterName));
+                        item.DisplayName = _showKey ? pmContentItem.Key : pmContentItem.Value;
+                        isfilter = true;
                     }
+              
                 }
                 return isfilter;
             };
+
+
+
+            DIDOVisibility = (INViewSource.Count > 0 || OutViewSource.Count > 0);
+            AIAOVisibility = (AIViewSource.Count > 0 || AOViewSource.Count > 0);
+            if (DIDOVisibility)
+            {
+                SelectedIndexData = 0;
+            }
+            else if (!DIDOVisibility && AIAOVisibility)
+            {
+                SelectedIndexData = 1;
+            }
         }
         #endregion
 
@@ -359,7 +420,44 @@ namespace FurnaceUI.Views.Maintenances
         {
             base.InvokeAfterUpdateProperty(data);
 
-            if (data[_diKey] != null)
+            if (data == null || data.Count == 0)
+            {
+                return;
+            }
+            if (data.ContainsKey(_aiKey) && !string.IsNullOrEmpty(_aiKey) && data[_aiKey] != null)
+            {
+                List<NotifiableIoItem> lstData = (List<NotifiableIoItem>)data[_aiKey];
+                Dictionary<string, float> dicValues = new Dictionary<string, float>();
+
+                for (int i = 0; i < lstData.Count; i++)
+                {
+                    dicValues[lstData[i].Name] = lstData[i].FloatValue;
+                }
+
+                foreach (IOItem<float> item in AIs)
+                {
+                    if (dicValues.ContainsKey(item.Name))
+                        item.Value = dicValues[item.Name];
+                }
+            }
+            if (data.ContainsKey(_aoKey) && !string.IsNullOrEmpty(_aoKey) && data[_aoKey] != null)
+            {
+                List<NotifiableIoItem> lstData = (List<NotifiableIoItem>)data[_aoKey];
+                Dictionary<string, float> dicValues = new Dictionary<string, float>();
+
+                for (int i = 0; i < lstData.Count; i++)
+                {
+                    dicValues[lstData[i].Name] = lstData[i].FloatValue;
+                }
+
+                foreach (IOItem<float> item in AOs)
+                {
+                    if (dicValues.ContainsKey(item.Name))
+                        item.Value = dicValues[item.Name];
+                }
+            }
+
+            if (data.ContainsKey(_diKey) && !string.IsNullOrEmpty(_diKey) && data[_diKey] != null)
             {
                 List<NotifiableIoItem> lstData = (List<NotifiableIoItem>)data[_diKey];
                 Dictionary<string, bool> dicValues = new Dictionary<string, bool>();
@@ -375,7 +473,7 @@ namespace FurnaceUI.Views.Maintenances
                         item.Value = dicValues[item.Name];
                 }
             }
-            if (data[_doKey] != null)
+            if (data.ContainsKey(_doKey) && !string.IsNullOrEmpty(_doKey) && data[_doKey] != null)
             {
                 List<NotifiableIoItem> lstData = (List<NotifiableIoItem>)data[_doKey];
                 Dictionary<string, bool> dicValues = new Dictionary<string, bool>();
@@ -391,6 +489,7 @@ namespace FurnaceUI.Views.Maintenances
                         item.Value = dicValues[item.Name];
                 }
             }
+
         }
         #endregion
 
@@ -405,11 +504,31 @@ namespace FurnaceUI.Views.Maintenances
                 $"Please be attention, direct control DO is generally forbidden, Are you sure you want to do the operation?\r\n {doItem.Name} = {!doItem.Value}",
                 "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
                 return;
+            var ioName = _isSimulatorMode ? doItem.Name : $"{ModuleName.PM1}.{doItem.Name}";
+            InvokeClient.Instance.Service.DoOperation("System.SetDoValue", ioName, !doItem.Value);
+        }
+        public void SetAO(AOItemFloat aoItem)
+        {
+            if (MessageBox.Show(
+                $"Please be attention, direct control AO is generally forbidden, Are you sure you want to do the operation?\r\n {aoItem.Name} = {aoItem.NewValueFloat}",
+                "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
+                return;
+            var ioName = _isSimulatorMode ? aoItem.Name : $"{ModuleName.PM1}.{aoItem.Name}";
+            InvokeClient.Instance.Service.DoOperation("System.SetAoValueFloat", ioName, aoItem.NewValueFloat);
 
-            InvokeClient.Instance.Service.DoOperation("System.SetDoValue", doItem.Name, !doItem.Value);
         }
+
         #endregion
 
+        private IOListEditView view;
+
+        protected override void OnViewLoaded(object view)
+        {
+
+            base.OnViewLoaded(view);
+            view = (IOListEditView)view;
+
+        }
         public List<string> BufferViews = new List<string>()
         {
           "DI_BufferStock4A",
@@ -436,11 +555,8 @@ namespace FurnaceUI.Views.Maintenances
     /// </summary>
     public class MyContentTemplateSelector : DataTemplateSelector
     {
-        public DataTemplate LoadPort1Template { get; set; }
-        public DataTemplate LoadPort2Template { get; set; }
-        public DataTemplate LoadPortTemplate { get; set; }
-        public DataTemplate Fims1Template { get; set; }
-        public DataTemplate Fims2Template { get; set; }
+        public DataTemplate CommonTemplate { get; set; }
+        public DataTemplate FoupTemplate { get; set; }
 
         public DataTemplate BufferTemplate { get; set; }
 
@@ -456,23 +572,13 @@ namespace FurnaceUI.Views.Maintenances
             {
                 switch (displayName)
                 {
-                    case "Load Port 1":                       
-                        //dataTemplate = LoadPort1Template;
-                        //break;
+                    case "Load Port 1":
                     case "Load Port 2":
-                        //dataTemplate = LoadPort2Template;
-                        //break;
                     case "Load Port 3":
-                        //dataTemplate = LoadPortTemplate;
-                        //break;
                     case "Load Port 4":
-                        dataTemplate = LoadPortTemplate;
-                        break;
                     case "Fims 1":
-                        dataTemplate = Fims1Template;
-                        break;
                     case "Fims 2":
-                        dataTemplate = Fims2Template;
+                        dataTemplate = FoupTemplate;
                         break;
                     case "Buffer":
                         dataTemplate = BufferTemplate;
@@ -487,6 +593,7 @@ namespace FurnaceUI.Views.Maintenances
                         dataTemplate = CarrierLoaderTemplate;
                         break;
                     default:
+                        dataTemplate = CommonTemplate;
                         break;
                 }
             }

+ 175 - 31
Furnace/FurnaceUI/Views/Maintenances/IOListView.xaml

@@ -14,7 +14,9 @@
             <RowDefinition />
             <RowDefinition Height="10" />
             <RowDefinition />
-            <RowDefinition Height="10"/>
+            <RowDefinition Height="10" />
+            <RowDefinition />
+            <RowDefinition Height="10" />
             <RowDefinition />
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
@@ -25,14 +27,18 @@
             <ColumnDefinition />
             <ColumnDefinition Width="10" />
             <ColumnDefinition />
+            <ColumnDefinition Width="10" />
+            <ColumnDefinition />
         </Grid.ColumnDefinitions>
         <Button
             Content="Load Port 1"
             FontFamily="Segoe"
-            FontSize="40">
+            FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoLP" />
+                        <cal:Parameter Value="LP1" />
                         <cal:Parameter Value="Load Port 1" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
@@ -42,124 +48,262 @@
             Grid.Column="2"
             Content="Load Port 2"
             FontFamily="Segoe"
-            FontSize="40">
+            FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoLP" />
+                        <cal:Parameter Value="LP2" />
                         <cal:Parameter Value="Load Port 2" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
         <Button
-     Grid.Column="4"
-     Content="Load Port 3"
-     FontFamily="Segoe"
-     FontSize="40">
+    Grid.Column="4"
+    Content="Load Port 3"
+    FontFamily="Segoe"
+    FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoLP" />
+                        <cal:Parameter Value="LP3" />
                         <cal:Parameter Value="Load Port 3" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
         <Button
-     Grid.Column="6"
-     Content="Load Port 4"
-     FontFamily="Segoe"
-     FontSize="40">
+Grid.Column="6"
+Content="Load Port 4"
+FontFamily="Segoe"
+FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoLP" />
+                        <cal:Parameter Value="LP4" />
                         <cal:Parameter Value="Load Port 4" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
+
         <Button
-            Grid.Column="0"
-            Grid.Row="4"
+               Grid.Row="2"
             Content="Fims 1"
             FontFamily="Segoe"
-            FontSize="40">
+            FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoFIMS" />
+                        <cal:Parameter Value="FIMS1" />
                         <cal:Parameter Value="Fims 1" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
         <Button
+              Grid.Row="2"
             Grid.Column="2"
-            Grid.Row="6"
             Content="Fims 2"
             FontFamily="Segoe"
-            FontSize="40">
+            FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoFIMS" />
+                        <cal:Parameter Value="FIMS2" />
                         <cal:Parameter Value="Fims 2" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
         <Button
-            Grid.Row="2"
-            Grid.Column="0"
-            Content="Buffer"
-            FontFamily="Segoe"
-            FontSize="40">
+    Grid.Row="2"
+    Grid.Column="4"
+    Content="Buffer"
+    FontFamily="Segoe"
+    FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoBufferMotor" />
+                        <cal:Parameter Value="BufferServo" />
                         <cal:Parameter Value="Buffer" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
+
         <Button
             Grid.Row="2"
-            Grid.Column="2"
-            Content="Boat"
+            Grid.Column="6"
+            Content="R Axis"
             FontFamily="Segoe"
-            FontSize="40">
+            FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoFurnaceMotor" />
+                        <cal:Parameter Value="BoatRotationServo" />
                         <cal:Parameter Value="Boat" />
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
+
         <Button
-            Grid.Row="2"
-            Grid.Column="4"
+            Grid.Row="4"
+            Grid.Column="6"
+            Content="Z Axis"
+            FontFamily="Segoe"
+            FontSize="30">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="Click">
+                    <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoFurnaceMotor" />
+                        <cal:Parameter Value="BoatElevatorServo" />
+                        <cal:Parameter Value="Boat" />
+                    </cal:ActionMessage>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+        </Button>
+        <Button
+    Grid.Column="8"
+    Content="EX1"
+    FontFamily="Segoe"
+    FontSize="30">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="Click">
+                    <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoStocker" />
+                        <cal:Parameter Value="Stocker17" />
+                        <cal:Parameter Value="Stocker17" />
+                    </cal:ActionMessage>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+        </Button>
+        <Button
+Grid.Column="8"
+Grid.Row="2"
+Content="EX2"
+FontFamily="Segoe"
+FontSize="30">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="Click">
+                    <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoStocker" />
+                        <cal:Parameter Value="Stocker18" />
+                        <cal:Parameter Value="Stocker18" />
+                    </cal:ActionMessage>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+        </Button>
+      
+        <Button
+            Grid.Row="4"
             Content="Wafer Robot"
             FontFamily="Segoe"
-            FontSize="40">
+            FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoWaferRobot" />
+                        <cal:Parameter Value="IoWaferRobot" />
                         <cal:Parameter Value="Wafer Robot" />
+
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
         <Button
-            Grid.Row="2"
-            Grid.Column="6"
+            Grid.Row="4"
+            Grid.Column="2"
             Content="Carrier Loader"
             FontFamily="Segoe"
-            FontSize="40">
+            FontSize="30">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="Click">
+                    <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoCarrierRobot" />
+                        <cal:Parameter Value="IoCarrierRobot" />
+                        <cal:Parameter Value="Carrier Robot" />
+
+                    </cal:ActionMessage>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+        </Button>
+        <Button
+     Grid.Row="4"
+     Grid.Column="4"
+     Content="Shutter"
+     FontFamily="Segoe"
+     FontSize="30">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="Click">
+                    <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoShutter" />
+                        <cal:Parameter Value="Shutter" />
+                        <cal:Parameter Value="Shutter" />
+
+                    </cal:ActionMessage>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+        </Button>
+        <Button
+ Grid.Row="4"
+ Grid.Column="8"
+ Content="AGVDoor"
+ FontFamily="Segoe"
+ FontSize="30">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="Click">
+                    <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoDoor" />
+                        <cal:Parameter Value="AGVDoor" />
+                        <cal:Parameter Value="AGVDoor" />
+
+                    </cal:ActionMessage>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+        </Button>
+
+        <Button
+Grid.Row="6"
+Content="Signal Ligh"
+FontFamily="Segoe"
+FontSize="30">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="Click">
+                    <cal:ActionMessage MethodName="BtnEdit">
+                        <cal:Parameter Value="IoSignalTower" />
+                        <cal:Parameter Value="SignalTower" />
+                        <cal:Parameter Value="SignalTower" />
+
+                    </cal:ActionMessage>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+        </Button>
+        <Button
+Grid.Row="6"
+            Grid.Column="2"
+Content="APC CKD"
+FontFamily="Segoe"
+FontSize="30">
             <i:Interaction.Triggers>
                 <i:EventTrigger EventName="Click">
                     <cal:ActionMessage MethodName="BtnEdit">
-                        <cal:Parameter Value="Carrier Loader" />
+                        <cal:Parameter Value="IoAPC" />
+                        <cal:Parameter Value="APC" />
+                        <cal:Parameter Value="APC" />
+
                     </cal:ActionMessage>
                 </i:EventTrigger>
             </i:Interaction.Triggers>
         </Button>
+ 
     </Grid>
 </UserControl>

+ 15 - 6
Furnace/FurnaceUI/Views/Maintenances/IOListViewModel.cs

@@ -1,6 +1,9 @@
-using Caliburn.Micro;
+using Aitex.Core.Util;
+using Caliburn.Micro;
 using Caliburn.Micro.Core;
+using DocumentFormat.OpenXml;
 using MECF.Framework.UI.Client.ClientBase;
+using System.Collections.Generic;
 
 namespace FurnaceUI.Views.Maintenances
 {
@@ -9,6 +12,7 @@ namespace FurnaceUI.Views.Maintenances
     /// </summary>
     public class IOListViewModel : UiViewModelBase, ISupportMultipleSystem
     {
+
         #region 构造函数
         /// <summary>
         /// 构造函数
@@ -24,7 +28,6 @@ namespace FurnaceUI.Views.Maintenances
         /// 系统名称
         /// </summary>
         public string SystemName { get; set; }
-        public bool IsPermission { get => this.Permission == 3; }
         #endregion
 
         #region 方法 编辑IOList
@@ -32,17 +35,23 @@ namespace FurnaceUI.Views.Maintenances
         /// 编辑IOList
         /// </summary>
         /// <param name="obj"></param>
-        public void BtnEdit(string tempStr)
+        public void BtnEdit(string typeName, string deviceName, string displayName)
         {
-            if (!string.IsNullOrEmpty(tempStr))
+            if (!string.IsNullOrEmpty(typeName) && !string.IsNullOrEmpty(deviceName))
             {
                 var windowManager = IoC.Get<IWindowManager>();
                 IOListEditViewModel editViewModel = new IOListEditViewModel();
                 editViewModel.SystemName = SystemName;
-                editViewModel.DisplayName = tempStr;      
-                (windowManager as WindowManager)?.ShowDialogWithTitle(editViewModel,this, null, tempStr);
+                editViewModel.TypeName = typeName;
+                editViewModel.DeviceName = deviceName;
+                editViewModel.DisplayName = displayName;
+                (windowManager as WindowManager)?.ShowDialogWithTitle(editViewModel, this, null, displayName);
             }
         }
+        protected override void InvokeAfterUpdateProperty(Dictionary<string, object> data)
+        {
+            base.InvokeAfterUpdateProperty(data);
+        }
         #endregion
     }
 }