Browse Source

新增螺丝供料器管理功能及锁付数据完善

本次提交主要内容:
- 新增螺丝供料器模型、配置与管理,支持增删改查
- 设置界面增加“螺丝供料器”Tab页及参数编辑
- 新增“添加螺丝供料器”对话框及相关命令
- 支持PLC压力值采集,完善锁付结果数据结构与导出
- 电批协议解析增加目标扭矩等设定值
- 多语言资源与项目依赖同步更新
- 优化界面交互与数据校验,提升系统可用性
孝锋 徐 8 months ago
parent
commit
91b41549be

+ 1 - 0
TeamAAS-VM/App.xaml.cs

@@ -165,6 +165,7 @@ namespace TeamAAS_VP
             containerRegistry.RegisterDialog<AddRobot>();
             containerRegistry.RegisterDialog<AddFeeder>();
             containerRegistry.RegisterDialog<AddPlc>();
+            containerRegistry.RegisterDialog<AddScrewFeeder>();
             containerRegistry.RegisterDialog<AddCamera>();
             containerRegistry.RegisterDialog<EditCamera>();
             containerRegistry.RegisterDialog<PalletManage>();

+ 45 - 41
TeamAAS-VM/Core/Management.cs

@@ -1053,11 +1053,11 @@ namespace TeamAAS_VP.Core
                 }
 
                 //获取产品编码
-                string productCode = plc.ReadNode<string>(addressConfig.In_Code.Address);
+                _productService.CurrentProductCode = plc.ReadNode<string>(addressConfig.In_Code.Address);
                 //如果产品编码为空,则以当前的时间戳作为编码
-                if (string.IsNullOrEmpty(productCode))
+                if (string.IsNullOrEmpty(_productService.CurrentProductCode))
                 {
-                    productCode = DateTime.Now.ToString("yyyyMMddHHmmssfff");
+                    _productService.CurrentProductCode = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                 }
 
                 // 触发下相机拍照
@@ -1309,44 +1309,48 @@ namespace TeamAAS_VP.Core
                             //位置编号
                             Int16 positionIndex = plc.ReadNode<Int16>(addressConfig.In_ProductNum.Address);
                             SendTaskMessage($"编号:{positionIndex}", MessageLevel.Info);
-                            ////获取当前锁付点
-                            //var screwPoint = currentProduct.ScrewPoints.FirstOrDefault(p=>p.Number== positionIndex);
-                            ////获取当前的机器人点位
-                            //var robot = _robotService.GetAllRobots().FirstOrDefault();
-                            //var currentPosition = robot.GetRobotPos();
-
-
-                            //await Task.Delay(60);
-                            ////获取电批结果
-                            //ScrewDriver.GetData();
-                            //LockResult lockResult=new LockResult();
-                            //lockResult.Number = positionIndex;
-                            //lockResult.LockPassed = ScrewDriver.Success;
-                            //lockResult.ProductNumber = "";
-                            //lockResult.LockTurns= (float)ScrewDriver.Truns;
-                            //lockResult.LockTorque= (float)ScrewDriver.TorqueValue;
-                            //lockResult.LockDuration= (float)ScrewDriver.FinalTime;
-                            //lockResult.ScrewdriverProgramNumber= ScrewDriver.ProgramNumber;
-                            //lockResult.ResultDetails = ScrewDriver.ErrorInfo;
-                            //lockResult.Pressure= 0;
-                            //lockResult.TargetTorque= 0;
-                            //lockResult.TargetTurnsUpperLimit= 0;
-                            //lockResult.TargetTurnsLowerLimit= 0;
-                            //lockResult.TargetLockSpeed= 0;
-                            //lockResult.StartPositionX= currentPosition.X;
-                            //lockResult.StartPositionY= currentPosition.Y;
-                            //lockResult.StartPositionZ= screwPoint.Z_Position_Start;
-                            //lockResult.EndPositionZ= currentPosition.Z;
-                            //lockResult.LockDescentSpeed= screwPoint.Z_Velocity_Stop;
-                            //lockResult.FeederNumber= screwPoint!=null?screwPoint.Feeder:0;
-                            //lockResult.NozzleNumber = "";
-                            //lockResult.OperatorName = "";
-                            //lockResult.WaveDatas= ScrewDriver.WaveDatas;
-                            //App.Current.Dispatcher.Invoke(() =>
-                            //{
-                            //    _eventAggregator.GetEvent<LockFinishNotification>().Publish(lockResult);
-                            //});
-                            //await _systemDatabaseService.RecordLockResultAsync(lockResult);
+                            //获取当前锁付点
+                            var screwPoint = currentProduct.ScrewPoints.FirstOrDefault(p => p.Number == positionIndex);
+                            //获取当前的机器人点位
+                            var robot = _robotService.GetAllRobots().FirstOrDefault();
+                            var currentPosition = robot.GetRobotPos();
+                            //读取压力值
+                            float pressure = plc.ReadNode<float>(addressConfig.In_PressureValue.Address);
+
+
+                            await Task.Delay(60);
+                            //获取电批结果
+                            bool isSucced= ScrewDriver.GetData();
+                            LockResult lockResult = new LockResult();
+                            lockResult.ScrewdriverGetDataSucceed = isSucced;
+                            lockResult.Number = positionIndex;
+                            lockResult.LockPassed = ScrewDriver.Success;
+                            lockResult.ProductNumber = _productService.CurrentProductCode;
+                            lockResult.LockTurns = (float)ScrewDriver.Truns;
+                            lockResult.LockTorque = (float)ScrewDriver.TorqueValue;
+                            lockResult.LockDuration = (float)ScrewDriver.FinalTime;
+                            lockResult.ScrewdriverProgramNumber = ScrewDriver.ProgramNumber;
+                            lockResult.ResultDetails = ScrewDriver.ErrorInfo;
+                            lockResult.Pressure = pressure;
+                            lockResult.TargetTorque = ScrewDriver.TargetTorque;
+                            lockResult.TargetTurnsUpperLimit = ScrewDriver.TargetTurnsUpperLimit;
+                            lockResult.TargetTurnsLowerLimit = ScrewDriver.TargetTurnsLowerLimit;
+                            lockResult.TargetLockSpeed = ScrewDriver.TargetLockSpeed;
+                            lockResult.StartPositionX = currentPosition.X;
+                            lockResult.StartPositionY = currentPosition.Y;
+                            lockResult.StartPositionZ = screwPoint.Z_Position_Start;
+                            lockResult.EndPositionZ = currentPosition.Z;
+                            lockResult.LockDescentSpeed = screwPoint.Z_Velocity_Stop;
+                            lockResult.FeederNumber = screwPoint != null ? screwPoint.Feeder : 0;
+                            lockResult.NozzleNumber = "";
+                            lockResult.OperatorName = _systemDatabaseService.GetCurrentUser().UserName;
+                            lockResult.ProductImagePath = "";
+                            lockResult.WaveDatas = ScrewDriver.WaveDatas;
+                            App.Current.Dispatcher.Invoke(() =>
+                            {
+                                _eventAggregator.GetEvent<LockFinishNotification>().Publish(lockResult);
+                            });
+                            await _systemDatabaseService.RecordLockResultAsync(lockResult);
                             await plc.WriteNodeAsync(addressConfig.In_WorkDone.Address, (Int16)0);
                         }
                         else

+ 33 - 5
TeamAAS-VM/Core/ScrewDriver/XYD_ScrewDriver.cs

@@ -4,6 +4,7 @@ using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System.Threading.Tasks;
+using System.Web.UI.WebControls;
 using TeamAAS_VP.Enums;
 using TeamAAS_VP.Interfaces;
 
@@ -89,14 +90,14 @@ namespace TeamAAS_VP.Core.ScrewDriver
         public double StrokeTorque5 { get; private set; }
 
         /// <summary>
-        /// 峰值扭矩(单位:N·m,协议返回值需乘以 0.001)。
+        /// 峰值扭矩(单位:kgf,协议返回值需乘以 0.001)。
         /// </summary>
         public double MaxTorque { get; private set; }
 
         public double OverlockAngle { get; private set; }
 
         /// <summary>
-        /// 过锁扭矩(单位:N·m)。
+        /// 过锁扭矩(单位:kgf)。
         /// </summary>
         public double OverlockTorque { get; private set; }
 
@@ -107,14 +108,14 @@ namespace TeamAAS_VP.Core.ScrewDriver
         public double FitAngleCheck { get; private set; }
 
         /// <summary>
-        /// 夹紧扭矩(单位:N·m)。
+        /// 夹紧扭矩(单位:fgf)。
         /// </summary>
         public double ClampingTorque { get; private set; }
 
         public double ClampingTorqueCheck { get; private set; }
 
         /// <summary>
-        /// 过程最大扭矩(单位:N·m)。
+        /// 过程最大扭矩(单位:kgf)。
         /// </summary>
         public double ProcessMaxTorque { get; private set; }
 
@@ -123,7 +124,7 @@ namespace TeamAAS_VP.Core.ScrewDriver
         public double FitAngle1 { get; private set; }
 
         /// <summary>
-        /// 贴合点扭矩(单位:N·m)。
+        /// 贴合点扭矩(单位:kgf)。
         /// </summary>
         public double FitTorque { get; private set; }
 
@@ -170,6 +171,27 @@ namespace TeamAAS_VP.Core.ScrewDriver
         /// </summary>
         public List<WaveData> WaveDatas { get; } = new List<WaveData>();
 
+        //设定值
+        /// <summary>
+        /// 目标扭矩
+        /// </summary>
+        public float TargetTorque { get; private set; }
+
+        /// <summary>
+        /// 目标圈数上限
+        /// </summary>
+        public float TargetTurnsUpperLimit {  get; private set; }
+
+        /// <summary>
+        /// 目标圈数下限
+        /// </summary>
+        public float TargetTurnsLowerLimit {  get; private set; }
+
+        /// <summary>
+        /// 目标锁付速度
+        /// </summary>
+        public float TargetLockSpeed {  get; private set; }
+
         #endregion
 
         #region 事件
@@ -231,6 +253,7 @@ namespace TeamAAS_VP.Core.ScrewDriver
                 {
                     return false;
                 }
+                DataAnalysis(data);
                 //if (data == null || !DataAnalysis(data))
                 //{
                 //    UpdateConnectState(true);
@@ -502,6 +525,11 @@ namespace TeamAAS_VP.Core.ScrewDriver
                 SectionOverLock = ToInt16(data, 100);
                 SectionFinalEnd = ToInt16(data, 102);
 
+                TargetTorque = ToInt16(data, 238) * 0.001f;//目标扭矩
+                TargetTurnsUpperLimit= ToInt16(data, 246);//最终旋转角度上限
+                TargetTurnsLowerLimit= ToInt16(data, 248);//最终旋转角度下限
+                TargetLockSpeed= ToInt16(data, 394);//停止速度
+
                 // 计算 TSPA 曲线数据段长度(协议: 在偏移 504/506 存有开始/结束索引或总数)
                 int length = ToInt16(data, 506) - ToInt16(data, 504);
                 if (length <= 0)

+ 5 - 0
TeamAAS-VM/Interfaces/IProductService.cs

@@ -11,6 +11,11 @@ namespace TeamAAS_VP.Interfaces
     /// </summary>
     public interface IProductService : IDisposable
     {
+        /// <summary>
+        /// 当前产品编号
+        /// </summary>
+        string CurrentProductCode { get; set; }
+
         /// <summary>
         /// 产品切换事件
         /// </summary>

+ 70 - 5
TeamAAS-VM/Models/LockResult.cs

@@ -154,6 +154,16 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref __TargetLockSpeed, value); }
         }
 
+        private bool _ScrewdriverGetDataSucceed;
+        /// <summary>
+        /// 电批数据是否获取成功
+        /// </summary>
+        public bool ScrewdriverGetDataSucceed
+        {
+            get { return _ScrewdriverGetDataSucceed; }
+            set { SetProperty(ref _ScrewdriverGetDataSucceed, value); }
+        }
+
         private float __StartPositionX;
         /// <summary>
         /// 锁付位置坐标 X 起始值
@@ -301,6 +311,9 @@ namespace TeamAAS_VP.Models
                 LockDescentSpeed = this.LockDescentSpeed,
                 FeederNumber = this.FeederNumber,
                 NozzleNumber = this.NozzleNumber,
+                OperatorName = this.OperatorName,
+                ProductImagePath = this.ProductImagePath,
+                ScrewdriverGetDataSucceed = this.ScrewdriverGetDataSucceed,
                 WaveDatas = new List<WaveData>(this.WaveDatas)
             };
         }
@@ -311,18 +324,70 @@ namespace TeamAAS_VP.Models
         /// <param name="filePath"></param>
         public void SaveToCsv(string filePath)
         {
-            using (var writer = new System.IO.StreamWriter(filePath))
+            string EscapeCsv(object value)
             {
-                // 写入锁付结果信息
-                writer.WriteLine("Number,ProductNumber,Timestamp,LockTurns,LockTorque,LockDuration,LockPassed,ScrewdriverProgramNumber,Pressure,TargetTorque,TargetTurnsUpperLimit,TargetTurnsLowerLimit,TargetLockSpeed,StartPositionX,StartPositionY,StartPositionZ,EndPositionZ,LockDescentSpeed,FeederNumber,NozzleNumber");
-                writer.WriteLine($"{Number},{ProductNumber},{Timestamp},{LockTurns},{LockTorque},{LockDuration},{LockPassed},{ScrewdriverProgramNumber},{Pressure},{TargetTorque},{TargetTurnsUpperLimit},{TargetTurnsLowerLimit},{TargetLockSpeed},{StartPositionX},{StartPositionY},{StartPositionZ},{EndPositionZ},{LockDescentSpeed},{FeederNumber},{NozzleNumber}");
+                if (value == null) return "\"\"";
+                string s;
+                if (value is DateTime dt)
+                {
+                    s = dt.ToString("o"); // ISO 8601
+                }
+                else
+                {
+                    s = Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture);
+                }
+                s = s.Replace("\"", "\"\""); // escape quotes
+                return $"\"{s}\"";
+            }
+
+            using (var writer = new System.IO.StreamWriter(filePath, false, System.Text.Encoding.UTF8))
+            {
+                // 写入锁付结果信息表头(已新增字段)
+                writer.WriteLine("Number,ProductNumber,Timestamp,LockTurns,LockTorque,LockDuration,LockPassed,ScrewdriverProgramNumber,Pressure,TargetTorque,TargetTurnsUpperLimit,TargetTurnsLowerLimit,TargetLockSpeed,StartPositionX,StartPositionY,StartPositionZ,EndPositionZ,LockDescentSpeed,FeederNumber,FeederBatchNumber,NozzleNumber,ResultDetails,ScrewdriverGetDataSucceed,OperatorName,ProductImagePath");
+                
+                // 写入锁付结果数据行(所有字段均做 CSV 转义)
+                writer.WriteLine(string.Join(",",
+                    EscapeCsv(Number),
+                    EscapeCsv(ProductNumber),
+                    EscapeCsv(Timestamp),
+                    EscapeCsv(LockTurns),
+                    EscapeCsv(LockTorque),
+                    EscapeCsv(LockDuration),
+                    EscapeCsv(LockPassed),
+                    EscapeCsv(ScrewdriverProgramNumber),
+                    EscapeCsv(Pressure),
+                    EscapeCsv(TargetTorque),
+                    EscapeCsv(TargetTurnsUpperLimit),
+                    EscapeCsv(TargetTurnsLowerLimit),
+                    EscapeCsv(TargetLockSpeed),
+                    EscapeCsv(StartPositionX),
+                    EscapeCsv(StartPositionY),
+                    EscapeCsv(StartPositionZ),
+                    EscapeCsv(EndPositionZ),
+                    EscapeCsv(LockDescentSpeed),
+                    EscapeCsv(FeederNumber),
+                    EscapeCsv(FeederBatchNumber),
+                    EscapeCsv(NozzleNumber),
+                    EscapeCsv(ResultDetails),
+                    EscapeCsv(ScrewdriverGetDataSucceed),
+                    EscapeCsv(OperatorName),
+                    EscapeCsv(ProductImagePath)
+                ));
+
                 // 写入波形数据
                 writer.WriteLine();
                 writer.WriteLine("WaveDataIndex,LockAngle,Torque,Turns,Speed,Slopes");
                 for (int i = 0; i < WaveDatas.Count; i++)
                 {
                     var waveData = WaveDatas[i];
-                    writer.WriteLine($"{i},{waveData.LockAngle},{waveData.Torque},{waveData.Turns},{waveData.Speed},{waveData.Slopes}");
+                    writer.WriteLine(string.Join(",",
+                        EscapeCsv(i),
+                        EscapeCsv(waveData.LockAngle),
+                        EscapeCsv(waveData.Torque),
+                        EscapeCsv(waveData.Turns),
+                        EscapeCsv(waveData.Speed),
+                        EscapeCsv(waveData.Slopes)
+                    ));
                 }
             }
         }

+ 16 - 0
TeamAAS-VM/Models/PLC/PlcAddressConfig.cs

@@ -469,6 +469,17 @@ namespace TeamAAS_VP.Models.PLC
             get { return _In_WorkDone; }
             set { SetProperty(ref _In_WorkDone, value); }
         }
+
+        private PlcAddress _In_PressureValue = new PlcAddress();
+        /// <summary>
+        /// 压力值
+        /// </summary>
+        public PlcAddress In_PressureValue
+        {
+            get { return _In_PressureValue; }
+            set { SetProperty(ref _In_PressureValue, value); }
+        }
+
         #endregion
 
         public PlcAddressConfig()
@@ -810,6 +821,11 @@ namespace TeamAAS_VP.Models.PLC
             In_WorkDone.DataType = "int16";
             In_WorkDone.Description = "锁附/组装结束 =1OK =2NG";
 
+            In_PressureValue = Ensure(In_PressureValue);
+            In_PressureValue.Address = "ns=4;s=DB_Communication|ToPC.PressureValue";
+            In_PressureValue.DataType = "float";
+            In_PressureValue.Description = "压力值";
+
             // 说明:若项目中 PlcAddress 的实际属性名或类型与此不同(例如使用枚举、不同字段名),
             // 请根据实际类型调整赋值。本方法主要提供合理的默认字符串地址、数据类型及描述,便于后续从配置覆盖。
         }

+ 3 - 0
TeamAAS-VM/Resources/Languages/Lang.resx

@@ -2120,4 +2120,7 @@
   <data name="相机焦距评价" xml:space="preserve">
     <value>相机焦距评价</value>
   </data>
+  <data name="螺丝供料器" xml:space="preserve">
+    <value>螺丝供料器</value>
+  </data>
 </root>

+ 5 - 0
TeamAAS-VM/Services/ProductService.cs

@@ -58,6 +58,11 @@ namespace TeamAAS_VP.Services
         /// </summary>
         public event Action<ProductModel> OnProductChanged;
 
+        /// <summary>
+        /// 当前产品编号
+        /// </summary>
+        public string CurrentProductCode { get; set; }
+
         /// <summary>
         /// 构造函数。
         /// </summary>

+ 8 - 0
TeamAAS-VM/TeamAAS-VP.csproj

@@ -529,6 +529,7 @@
     <Compile Include="Events\MainTabSwitchNotification.cs" />
     <Compile Include="Models\Feeder\ScrewFeederInfo.cs" />
     <Compile Include="Models\ScrewFeederBatchRecord.cs" />
+    <Compile Include="ViewModels\Setting\AddScrewFeederViewModel.cs" />
     <Compile Include="ViewModels\Statistics\LockResultRecoredQueryViewModel.cs" />
     <Compile Include="Views\DebugMod\FocusAnalyzerl.xaml.cs">
       <DependentUpon>FocusAnalyzerl.xaml</DependentUpon>
@@ -1015,6 +1016,9 @@
     <Compile Include="Views\Setting\AddRobot.xaml.cs">
       <DependentUpon>AddRobot.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Views\Setting\AddScrewFeeder.xaml.cs">
+      <DependentUpon>AddScrewFeeder.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Views\Setting\EditCamera.xaml.cs">
       <DependentUpon>EditCamera.xaml</DependentUpon>
     </Compile>
@@ -1370,6 +1374,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Views\Setting\AddScrewFeeder.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Views\Setting\EditCamera.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 84 - 0
TeamAAS-VM/ViewModels/Setting/AddScrewFeederViewModel.cs

@@ -0,0 +1,84 @@
+using Prism.Commands;
+using Prism.Mvvm;
+using Prism.Services.Dialogs;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using TeamAAS_VP.Core;
+using TeamAAS_VP.Models;
+using TeamAAS_VP.Models.Feeder;
+using TeamAAS_VP.Resources.Languages;
+
+namespace TeamAAS_VP.ViewModels.Setting
+{
+
+    public class AddScrewFeederViewModel : BindableBase, IDialogAware
+    {
+        private ScrewFeederInfo _SelectedScrewFeeder;
+        public ScrewFeederInfo SelectedScrewFeeder
+        {
+            get { return _SelectedScrewFeeder; }
+            set { SetProperty(ref _SelectedScrewFeeder, value); }
+        }
+
+        private DelegateCommand _ConfirmCommand;
+        public DelegateCommand ConfirmCommand =>
+            _ConfirmCommand ?? (_ConfirmCommand = new DelegateCommand(ExecuteConfirmCommand));
+
+        void ExecuteConfirmCommand()
+        {
+            if (string.IsNullOrEmpty(SelectedScrewFeeder.Name))
+            {
+                return;
+            }
+            if (!FileHelper.CheckFileName(SelectedScrewFeeder.Name))
+            {
+                MessageBox.Show(Lang.AddCameraVM_message1, "AAS", MessageBoxButton.OK, MessageBoxImage.Error);
+                return;
+            }
+
+            IDialogParameters parameters = new DialogParameters();
+            parameters.Add("ScrewFeeder", SelectedScrewFeeder);
+            Tuple<bool, ScrewFeederInfo> rest = new Tuple<bool, ScrewFeederInfo>(false, SelectedScrewFeeder);
+            RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
+        }
+
+        private DelegateCommand _CancelCommand;
+        public DelegateCommand CancelCommand =>
+            _CancelCommand ?? (_CancelCommand = new DelegateCommand(ExecuteCancelCommand));
+
+        void ExecuteCancelCommand()
+        {
+            IDialogParameters parameters = new DialogParameters();
+            parameters.Add("ScrewFeeder", SelectedScrewFeeder);
+            Tuple<bool, ScrewFeederInfo> rest = new Tuple<bool, ScrewFeederInfo>(false, SelectedScrewFeeder);
+            RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel, parameters));
+        }
+
+        public AddScrewFeederViewModel()
+        {
+
+        }
+
+        public string Title { get; set; } = "添加螺丝供料器";
+
+        public event Action<IDialogResult> RequestClose;
+
+        public bool CanCloseDialog()
+        {
+            return true;
+        }
+
+        public void OnDialogClosed()
+        {
+
+        }
+
+        public void OnDialogOpened(IDialogParameters parameters)
+        {
+            Title = "增加螺丝供料器";
+            SelectedScrewFeeder = new ScrewFeederInfo() { Id = Guid.NewGuid() };
+        }
+    }
+}

+ 129 - 0
TeamAAS-VM/ViewModels/SettingViewModel.cs

@@ -26,6 +26,7 @@ using TeamAAS_VP.Enums;
 using TeamAAS_VP.Events;
 using TeamAAS_VP.Interfaces;
 using TeamAAS_VP.Models;
+using TeamAAS_VP.Models.Feeder;
 using TeamAAS_VP.Models.Lights;
 using TeamAAS_VP.Resources.Languages;
 using TeamAAS_VP.Services;
@@ -162,6 +163,23 @@ namespace TeamAAS_VP.ViewModels
             set { SetProperty(ref _SelectCamera, value); }
         }
 
+        private ObservableCollection<ScrewFeederInfo> _ScrewFeederList;
+        /// <summary>
+        /// 螺丝供料器列表
+        /// </summary>
+        public ObservableCollection<ScrewFeederInfo> ScrewFeederList
+        {
+            get { return _ScrewFeederList; }
+            set { SetProperty(ref _ScrewFeederList, value); }
+        }
+
+        private ScrewFeederInfo _SelectScrewFeeder;
+        public ScrewFeederInfo SelectScrewFeeder
+        {
+            get { return _SelectScrewFeeder; }
+            set { SetProperty(ref _SelectScrewFeeder, value); }
+        }
+
         private double _Title1;
 
         public double Title1
@@ -383,6 +401,20 @@ namespace TeamAAS_VP.ViewModels
 
         private DelegateCommand _SaveLightControllersCommand;
         public DelegateCommand SaveLightControllersCommand => _SaveLightControllersCommand ?? (_SaveLightControllersCommand = new DelegateCommand(ExecuteSaveLightControllersCommand));
+
+        private DelegateCommand _AddScrewFeederCommand;
+        public DelegateCommand AddScrewFeederCommand =>
+            _AddScrewFeederCommand ?? (_AddScrewFeederCommand = new DelegateCommand(ExecuteAddScrewFeederCommand));
+
+        private DelegateCommand _RemoveScrewFeederCommand;
+        public DelegateCommand RemoveScrewFeederCommand =>
+            _RemoveScrewFeederCommand ?? (_RemoveScrewFeederCommand = new DelegateCommand(ExecuteRemoveScrewFeederCommand));
+
+        private DelegateCommand _SaveScrewFeedersCommand;
+        public DelegateCommand SaveScrewFeedersCommand =>
+            _SaveScrewFeedersCommand ?? (_SaveScrewFeedersCommand = new DelegateCommand(ExecuteSaveScrewFeedersCommand));
+
+       
         #endregion
 
         #region 事件
@@ -928,6 +960,103 @@ namespace TeamAAS_VP.ViewModels
         }
         #endregion
 
+        #region 螺丝供料器
+        /// <summary>
+        /// 保存所有螺丝供料器
+        /// </summary>
+        async void ExecuteSaveScrewFeedersCommand()
+        {
+            var view = new ShowMessage($"AAS", "是否保存螺丝供料器?");
+            var result = await DialogHost.Show(view, "RootDialog", null, null, null);
+            if (result != null && result is bool && (bool)result)
+            {
+                if (ScrewFeederList != null)
+                {
+                    foreach (var item in ScrewFeederList)
+                    {
+                        try
+                        {
+                            _configService.AddOrUpdateScrewFeeder(item);
+                        }
+                        catch (Exception ex)
+                        {
+                            // 记录或通知错误,但继续处理其它项
+                            _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 });
+                        }
+                    }
+                }
+                _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = Lang.完成, Duration = 1 });
+            }
+        }
+
+        /// <summary>
+        /// 移除螺丝供料器
+        /// </summary>
+        void ExecuteRemoveScrewFeederCommand()
+        {
+            if (SelectScrewFeeder == null) return;
+
+            if (MessageBox.Show("是否移除螺丝供料器?", "AAS", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
+            {
+                try
+                {
+                    var toRemove = ScrewFeederList?.FirstOrDefault(s => s.Id == SelectScrewFeeder.Id);
+                    if (toRemove != null)
+                    {
+                        _configService.RemoveScrewFeeder(toRemove.Id);
+
+                        // 重新加载列表以保持序号/配置一致(与其他类似实现一致)
+                        var root = _configService.GetAllScrewFeeders();
+                        ScrewFeederList = new ObservableCollection<ScrewFeederInfo>(root);
+
+                        _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "移除完成", Duration = 1 });
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 });
+                }
+            }
+        }
+
+        /// <summary>
+        /// 添加螺丝供料器
+        /// </summary>
+        void ExecuteAddScrewFeederCommand()
+        {
+            _dialogService.ShowDialog("AddScrewFeeder", rst =>
+            {
+                ButtonResult result1 = rst.Result;
+
+                if (result1 == ButtonResult.OK)
+                {
+                    var param = rst.Parameters.GetValue<ScrewFeederInfo>("ScrewFeeder");
+                    if (param != null)
+                    {
+                        if (ScrewFeederList == null)
+                        {
+                            ScrewFeederList = new ObservableCollection<ScrewFeederInfo>();
+                        }
+
+                        try
+                        {
+                            param=_configService.AddOrUpdateScrewFeeder(param);
+                            // 直接添加对话框返回的对象(也可以根据需要映射字段)
+                            ScrewFeederList.Add(param);
+                        }
+                        catch (Exception ex)
+                        {
+                            _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 });
+                        }
+
+                        _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "添加完成", Duration = 1 });
+                    }
+                }
+
+            });
+        }
+        #endregion
+
         #region 通讯
         async void ExecuteSaveCommunicateCommand(string parm)
         {

+ 6 - 1
TeamAAS-VM/Views/Home/ShowVisionRender.xaml.cs

@@ -3,6 +3,7 @@ using Cognex.VisionPro.ImageFile;
 using log4net.Core;
 using MahApps.Metro.Controls;
 using Prism.Events;
+using Prism.Ioc;
 using System;
 using System.Collections.Generic;
 using System.Drawing;
@@ -12,14 +13,16 @@ using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Forms.Integration;
 using System.Windows.Interop;
+using TeamAAS_VP;
 using TeamAAS_VP.Core;
+using TeamAAS_VP.Data;
 using TeamAAS_VP.Enums;
 using TeamAAS_VP.Events;
+using TeamAAS_VP.Interfaces;
 using TeamAAS_VP.Models;
 using TeamAAS_VP.Resources.Languages;
 using TeamAAS_VP.ViewModels;
 using TeamAAS_VP.ViewModels.Home;
-using TeamAAS_VP;
 using static MaterialDesignThemes.Wpf.Theme.ToolBar;
 
 namespace TeamAAS_VP.Views.Home
@@ -33,6 +36,7 @@ namespace TeamAAS_VP.Views.Home
         Dictionary<Guid, WindowsFormsHost> vmRenders;
         Dictionary<Guid, TextBlock> Titles;
         IEventAggregator _eventAggregator;
+        ISystemDatabaseService _systemDatabaseService;
         public ShowVisionRender()
         {
             InitializeComponent();
@@ -40,6 +44,7 @@ namespace TeamAAS_VP.Views.Home
             Titles = new Dictionary<Guid, TextBlock>();
             viewModel = DataContext as ShowVisionRenderViewModel;
             _eventAggregator = viewModel._eventAggregator;
+            _systemDatabaseService= ((Prism.PrismApplicationBase)App.Current).Container.Resolve<ISystemDatabaseService>();
             viewModel.UpdateLayout += ViewModel_UpdateLayout;
             _eventAggregator.GetEvent<RenderUpdateNotification>().Subscribe(UpdateRenderModuleSource);
             _eventAggregator.GetEvent<ProductChangedNotification>().Subscribe(ProductChanged);

+ 114 - 0
TeamAAS-VM/Views/Setting/AddScrewFeeder.xaml

@@ -0,0 +1,114 @@
+<UserControl x:Class="TeamAAS_VP.Views.Setting.AddScrewFeeder"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:prism="http://prismlibrary.com/"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+             xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
+             xmlns:sys="clr-namespace:System;assembly=mscorlib"
+             xmlns:enums="clr-namespace:TeamAAS_VP.Enums"
+             xmlns:convert="clr-namespace:TeamAAS_VP.ValueConverter"
+             xmlns:valRules="clr-namespace:TeamAAS_VP.Identity"
+             xmlns:validationRule="clr-namespace:TeamAAS_VP.ValidationRules"
+             xmlns:ext="clr-namespace:TeamAAS_VP.Extension"
+             xmlns:lex="http://wpflocalizeextension.codeplex.com"
+             xmlns:vm="clr-namespace:TeamAAS_VP.ViewModels.Setting"
+             lex:LocalizeDictionary.DesignCulture="zh-CN"
+             lex:ResxLocalizationProvider.DefaultAssembly="TeamAAS-VP"
+             lex:ResxLocalizationProvider.DefaultDictionary="Lang"
+             mc:Ignorable="d"
+             d:Background="White"
+             d:DataContext="{d:DesignInstance Type=vm:AddScrewFeederViewModel}"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             FontFamily="{DynamicResource DefaultFont}">
+    <prism:Dialog.WindowStyle>
+        <Style TargetType="Window">
+            <Setter Property="prism:Dialog.WindowStartupLocation"
+                    Value="CenterScreen" />
+            <Setter Property="WindowStyle"
+                    Value="None" />
+            <Setter Property="AllowDrop"
+                    Value="True" />
+            <Setter Property="BorderThickness"
+                    Value="0" />
+            <Setter Property="ShowInTaskbar"
+                    Value="False" />
+            <Setter Property="SizeToContent"
+                    Value="WidthAndHeight" />
+            <Setter Property="WindowState"
+                    Value="Normal" />
+            <Setter Property="Topmost"
+                    Value="True" />
+        </Style>
+    </prism:Dialog.WindowStyle>
+    <Grid HorizontalAlignment="Center">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="*" />
+            <RowDefinition Height="50" />
+        </Grid.RowDefinitions>
+
+        <!--参数详情-->
+        <Grid Margin="20,20">
+            <!-- 布局:两列,左侧标签固定宽度,右侧输入占满 -->
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="140" />
+                <ColumnDefinition Width="*"  MinWidth="150"/>
+            </Grid.ColumnDefinitions>
+
+            <Grid.RowDefinitions>
+                <RowDefinition Height="36" />  <!-- 名称 -->
+            </Grid.RowDefinitions>
+
+            <!-- 名称 -->
+            <TextBlock Grid.Row="0"
+                       Grid.Column="0"
+                       VerticalAlignment="Center"
+                       Foreground="{DynamicResource PrimaryHueMidBrush}"
+                       Text="{lex:Loc 名称}" />
+            <TextBox x:Name="txt_Name"
+                     Grid.Row="0"
+                     Grid.Column="1"
+                     VerticalContentAlignment="Center"
+                     Margin="0,4,0,4"
+                     materialDesign:HintAssist.Hint="请填写名称"
+                     Text="{Binding SelectedScrewFeeder.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
+        </Grid>
+        <StackPanel Grid.Row="1"
+                    Orientation="Horizontal"
+                    HorizontalAlignment="Right">
+            <Button Height="30"
+                    materialDesign:ButtonAssist.CornerRadius="10"
+                    ToolTip="{lex:Loc 确定}"
+                    Command="{Binding ConfirmCommand}">
+                <TextBlock Text="{lex:Loc 确定}" />
+                <Button.Style>
+                    <Style TargetType="Button"
+                           BasedOn="{StaticResource MaterialDesignRaisedButton}">
+                        <Style.Triggers>
+                            <MultiDataTrigger>
+                                <MultiDataTrigger.Conditions>
+                                    <!-- 当且仅当名称和端口无校验错误时,启用按钮 -->
+                                    <Condition Binding="{Binding ElementName=txt_Name, Path=(Validation.HasError)}"
+                                               Value="False" />
+                                    <Condition Binding="{Binding ElementName=txt_Port, Path=(Validation.HasError)}"
+                                               Value="False" />
+                                </MultiDataTrigger.Conditions>
+                                <Setter Property="IsEnabled"
+                                        Value="True" />
+                            </MultiDataTrigger>
+                        </Style.Triggers>
+                    </Style>
+                </Button.Style>
+            </Button>
+            <Button Height="30"
+                    Margin="20,0"
+                    materialDesign:ButtonAssist.CornerRadius="10"
+                    Style="{StaticResource MaterialDesignRaisedButton}"
+                    ToolTip="{lex:Loc 取消}"
+                    Command="{Binding CancelCommand}">
+                <TextBlock Text="{lex:Loc 取消}" />
+            </Button>
+        </StackPanel>
+    </Grid>
+</UserControl>

+ 15 - 0
TeamAAS-VM/Views/Setting/AddScrewFeeder.xaml.cs

@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace TeamAAS_VP.Views.Setting
+{
+    /// <summary>
+    /// Interaction logic for AddScrewFeeder
+    /// </summary>
+    public partial class AddScrewFeeder : UserControl
+    {
+        public AddScrewFeeder()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 218 - 1
TeamAAS-VM/Views/SettingView.xaml

@@ -22,7 +22,7 @@
              lex:LocalizeDictionary.DesignCulture="zh-CN"
              mc:Ignorable="d"
              d:DataContext="{d:DesignInstance Type=vm:SettingViewModel}"
-             d:Height="600"
+             d:Height="1080"
              d:Width="1024"
              d:Background="White"
              x:Class="TeamAAS_VP.Views.SettingView"
@@ -1559,6 +1559,223 @@
                     </ScrollViewer>
                 </Grid>
             </TabItem>
+            
+            <!--螺丝供料器-->
+            <TabItem>
+                <TabItem.Header>
+                    <StackPanel HorizontalAlignment="Stretch">
+                        <materialDesign:PackIcon Width="24"
+                                                 Height="24"
+                                                 HorizontalAlignment="Center"
+                                                 Kind="Screwdriver" />
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
+                                   FontSize="{DynamicResource Font.Size.Body2}"
+                                   Text="{lex:Loc 螺丝供料器}"
+                                   HorizontalAlignment="Stretch" />
+                    </StackPanel>
+                </TabItem.Header>
+                <Grid Margin="16">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="50" />
+                        <RowDefinition Height="*" />
+                    </Grid.RowDefinitions>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="auto" />
+                        <ColumnDefinition Width="*" />
+                    </Grid.ColumnDefinitions>
+                    <!--增删改查-->
+                    <StackPanel Grid.ColumnSpan="2"
+                                IsEnabled="{Binding IsAllowEdit}"
+                                Orientation="Horizontal">
+                        <Button Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
+                                ToolTip="增加螺丝供料器"
+                                Command="{Binding AddScrewFeederCommand}">
+                            <materialDesign:PackIcon Kind="Plus" />
+                        </Button>
+
+                        <Button Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}"
+                                ToolTip="移除螺丝供料器"
+                                Margin="20,0"
+                                Command="{Binding RemoveScrewFeederCommand}">
+                            <materialDesign:PackIcon Kind="DeleteForeverOutline" />
+                        </Button>
+                        <Button Style="{StaticResource MaterialDesignFloatingActionMiniSecondaryDarkButton}"
+                                ToolTip="{lex:Loc 保存}"
+                                Command="{Binding SaveScrewFeedersCommand}">
+                            <materialDesign:PackIcon Kind="ContentSaveCheck" />
+                        </Button>
+
+                    </StackPanel>
+                    <!--PLC列表-->
+                    <TreeView Grid.Row="1"
+                              Grid.Column="0"
+                              SelectedItemChanged="TreeView_SelectedItemChanged">
+                        <TreeViewItem Header="螺丝供料器列表"
+                                      FontSize="{DynamicResource Font.Size.Title4}"
+                                      FontWeight="Bold"
+                                      IsExpanded="True"
+                                      ItemsSource="{Binding ScrewFeederList}">
+                            <TreeViewItem.ItemTemplate>
+                                <HierarchicalDataTemplate>
+                                    <StackPanel Orientation="Vertical">
+                                        <TextBlock FontSize="{DynamicResource Font.Size.Title4}">
+                                            <TextBlock.Text>
+                                                <MultiBinding StringFormat="{}{0} . {1}">
+                                                    <Binding Path="FeederNumber" />
+                                                    <Binding Path="Name" />
+                                                </MultiBinding>
+                                            </TextBlock.Text>
+                                        </TextBlock>
+                                        <StackPanel Orientation="Horizontal">
+                                            <TextBlock Text="每包螺丝的数量:"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}"
+                                                       Margin="10,0,0,0" />
+                                            <TextBlock Text="{Binding PackSize,Mode=TwoWay}"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}" />
+                                        </StackPanel>
+                                        <StackPanel Orientation="Horizontal">
+                                            <TextBlock Text="低量报警阈值:"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}"
+                                                       Margin="10,0,0,0" />
+                                            <TextBlock Text="{Binding LowLevelThreshold,Mode=TwoWay}"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}" />
+                                        </StackPanel>
+                                        <StackPanel Orientation="Horizontal">
+                                            <TextBlock Text="是否启用低量报警:"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}"
+                                                       Margin="10,0,0,0" />
+                                            <CheckBox IsChecked="{Binding LowLevelAlarmEnabled,Mode=TwoWay}"
+                                                      IsEnabled="False"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}" />
+                                        </StackPanel>
+                                        <Border Height="2"
+                                                Margin="0"
+                                                BorderThickness="2"
+                                                BorderBrush="Green" />
+                                    </StackPanel>
+                                </HierarchicalDataTemplate>
+                            </TreeViewItem.ItemTemplate>
+                        </TreeViewItem>
+                    </TreeView>
+                    <!--参数详情-->
+                    <ScrollViewer Grid.Row="1"
+                                  IsEnabled="{Binding IsAllowEdit}"
+                                  Grid.Column="1"
+                                  Margin="20"
+                                  HorizontalAlignment="Left"
+                                  VerticalAlignment="Top"
+                                  Visibility="{Binding SelectScrewFeeder,Converter={StaticResource ObjectToVisibilityConverter}}">
+                        <Grid>
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="40" />
+                            </Grid.RowDefinitions>
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="auto" />
+                                <ColumnDefinition Width="200" />
+                                <ColumnDefinition Width="*" />
+                            </Grid.ColumnDefinitions>
+
+                            <!-- Id -->
+                            <TextBlock Text="Id: "
+                                       Grid.Row="0"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <TextBlock Text="{Binding SelectScrewFeeder.Id}"
+                                       Grid.Row="0"
+                                       Grid.Column="1"
+                                       Margin="10,0"
+                                       VerticalAlignment="Center" />
+
+                            <!-- Name -->
+                            <TextBlock Text="{lex:Loc 名称, Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
+                                       Grid.Row="1"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <TextBox Grid.Row="1"
+                                     Grid.Column="1"
+                                     Margin="10,0"
+                                     Text="{Binding SelectScrewFeeder.Name,Mode=TwoWay}" />
+
+                            <!-- 供料器编号 -->
+                            <!--<TextBlock Text="供料器编号:"
+                                       Grid.Row="2"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <TextBox Text="{Binding SelectScrewFeeder.FeederNumber,Mode=TwoWay}"
+                                     Grid.Row="2"
+                                     Grid.Column="1"
+                                     Margin="10,0"
+                                     Width="200"
+                                     TextAlignment="Center" />-->
+
+                            <!-- 每包螺丝数量 -->
+                            <TextBlock Text="每包螺丝数量:"
+                                       Grid.Row="3"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <mah:NumericUpDown Grid.Row="3"
+                                               Grid.Column="1"
+                                               Margin="10,0"
+                                               Width="200"
+                                               Minimum="0"
+                                               Maximum="10000"
+                                               Value="{Binding SelectScrewFeeder.PackSize,Mode=TwoWay}"
+                                               FontSize="{DynamicResource Font.Size.Body3}" />
+
+                            <!-- 低量报警阈值 -->
+                            <TextBlock Text="低量报警阈值:"
+                                       Grid.Row="4"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <mah:NumericUpDown Grid.Row="4"
+                                               Grid.Column="1"
+                                               Margin="10,0"
+                                               Width="200"
+                                               Minimum="0"
+                                               Maximum="10000"
+                                               Value="{Binding SelectScrewFeeder.LowLevelThreshold,Mode=TwoWay}"
+                                               FontSize="{DynamicResource Font.Size.Body3}" />
+
+                            <!-- 是否启用低量报警 -->
+                            <TextBlock Grid.Row="5"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <CheckBox Grid.Row="5"
+                                      Grid.Column="1"
+                                      Margin="10,0"
+                                      IsChecked="{Binding SelectScrewFeeder.LowLevelAlarmEnabled,Mode=TwoWay}"
+                                      VerticalAlignment="Center" />
+
+                            
+                        </Grid>
+                    </ScrollViewer>
+                </Grid>
+            </TabItem>
+
 
             <!--通讯-->
             <TabItem>

+ 5 - 0
TeamAAS-VM/Views/SettingView.xaml.cs

@@ -5,6 +5,7 @@ using Prism.Regions;
 using System;
 using System.Windows.Controls;
 using TeamAAS_VP.Models;
+using TeamAAS_VP.Models.Feeder;
 using TeamAAS_VP.Models.Lights;
 using TeamAAS_VP.ViewModels;
 
@@ -46,6 +47,10 @@ namespace TeamAAS_VP.Views
                 {
                     viewModel.SelectLightController = e.NewValue as LightControllerConfig;
                 }
+                else if (e.NewValue is ScrewFeederInfo)
+                {
+                    viewModel.SelectScrewFeeder = e.NewValue as ScrewFeederInfo;
+                }
             }
             catch (Exception)
             {