using MainShell.Common; using MainShell.EventArgsFolder; using MainShell.Hardware; using MainShell.Manual.Model; using MainShell.Models; using MainShell.Process; using MainShell.ProcessResult; using MainShell.Recipe.Models; using MainShell.Resources.CustomControl; using Stylet; using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; namespace MainShell.Manual.ViewModel { public class MarkResultModel : PropertyChangedBase { private int _id; public int Id { get { return _id; } set { SetAndNotify(ref _id, value); } } private MPoint _basePos; public MPoint BasePose { get { return _basePos; } set { SetAndNotify(ref _basePos, value); } } private MPoint _resultPose; public MPoint ResultPose { get { return _resultPose; } set { SetAndNotify(ref _resultPose, value); } } } // 实现3个事件接口 public class SubstratePositionViewModel : OperateViewModelBase, IHandle, IHandle, IHandle { private sealed class DelegateCommand : ICommand { private readonly Action _execute; public DelegateCommand(Action execute) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); } public event EventHandler CanExecuteChanged { add { } remove { } } public bool CanExecute(object parameter) { return true; } public void Execute(object parameter) { _execute(parameter); } } // 属性定义保持不变... private ObservableCollection _markResults = new ObservableCollection(); public ObservableCollection MarkResults { get { return _markResults; } set { SetAndNotify(ref _markResults, value); } } private int _row; public int RowIndex { get { return _row; } set { SetAndNotify(ref _row, value); } } private int _col; public int ColumnIndex { get { return _col; } set { SetAndNotify(ref _col, value); } } private int _rowMax; public int RowMax { get { return _rowMax; } set { SetAndNotify(ref _rowMax, value); } } private int _colMax; public int ColMax { get { return _colMax; } set { SetAndNotify(ref _colMax, value); } } private double _substrateAngle; public double SubstrateAngle { get { return _substrateAngle; } set { SetAndNotify(ref _substrateAngle, value); } } private DieMapModel _substrateMapModel = new DieMapModel(); public DieMapModel SubstrateMapModel { get => _substrateMapModel; set => SetAndNotify(ref _substrateMapModel, value); } private bool _isClickEnabled = true; public bool IsClickEnabled { get => _isClickEnabled; set => SetAndNotify(ref _isClickEnabled, value); } public ICommand DieClickedCommand { get; private set; } private readonly HardwareManager _hardwareManager; private readonly RecipeManager _recipeManager; private readonly IEventAggregator _eventAggregator; // 引用 EventAggregator private readonly ProcessResultManager _processResultManager; private readonly SubstratePositionMotionService _substratePositionMotionService; public SubstratePositionViewModel(HardwareManager hardwareManager, RecipeManager recipeManager, IEventAggregator eventAggregator, ProcessResultManager processResultManager, SubstratePositionMotionService substratePositionMotionService) { _recipeManager = recipeManager ?? throw new ArgumentNullException(nameof(recipeManager)); _hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager)); _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator)); _processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager)); _substratePositionMotionService = substratePositionMotionService ?? throw new ArgumentNullException(nameof(substratePositionMotionService)); _eventAggregator.Subscribe(this); DieClickedCommand = new DelegateCommand(ExecuteDieClicked); _cameraAxisViewModel = IoC.Get(); _cameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = hardwareManager.CameraAxisManager.TopCameraAxisDevices; } private void ExecuteDieClicked(object parameter) { if (!(parameter is ValueTuple)) { return; } ValueTuple dieInfo = (ValueTuple)parameter; OnDieClicked(this, new DieMapControl.DieClickedEventArgs(dieInfo.Item1, dieInfo.Item2, dieInfo.Item3)); } public void Handle(SubstrateProcessStartedEventArgs message) { Stylet.Execute.OnUIThread(() => { MarkResults.Clear(); SubstrateAngle = 0; }); } // 2. 找到 Mark 点:更新列表 public void Handle(SubstrateMarkFoundEventArgs message) { Stylet.Execute.OnUIThread(() => { var existing = MarkResults.FirstOrDefault(x => x.Id == message.Id); if (existing != null) { existing.BasePose = message.BasePose; existing.ResultPose = message.ResultPose; } else { MarkResults.Add(new MarkResultModel { Id = message.Id, BasePose = message.BasePose, ResultPose = message.ResultPose }); } }); } // 3. 计算完成:更新角度 public void Handle(SubstrateResultEventArgs message) { Stylet.Execute.OnUIThread(() => { SubstrateAngle = message.Angle; }); } // 手动启动流程 public async Task StartProcess() { var context = new MW.WorkFlow.WorkflowContext(); context[WorkflowContextKeys.EventAggregator] = _eventAggregator; context[WorkflowContextKeys.RecipeManager] = _recipeManager; context[WorkflowContextKeys.ProcessResultManager] = _processResultManager; context[WorkflowContextKeys.WorkflowName] = ProcessFlowName.SubstratePositionFlow; await RunManualActivityAsync(new MainShell.Process.SubstratePositionActivity(ProcessFlowName.SubstratePositionFlow, _substratePositionMotionService), context); } protected override void OnViewLoaded() { base.OnViewLoaded(); if (_recipeManager.CurrentSubstrateRecipe != null && _recipeManager.CurrentSubstrateRecipe.SubstrateInfo != null) { RowMax = _recipeManager.CurrentSubstrateRecipe.SubstrateInfo.RowNumber; ColMax = _recipeManager.CurrentSubstrateRecipe.SubstrateInfo.ColNumber; // 初始化基板Map if (RowMax > 0 && ColMax > 0) { SubstrateMapModel.Initialize(RowMax, ColMax); for (int r = 0; r < RowMax; r++) { for (int c = 0; c < ColMax; c++) { SubstrateMapModel.SetDieState(r, c, DieState.Available); } } } } } public void OnDieClicked(object sender, DieMapControl.DieClickedEventArgs e) { if (!IsClickEnabled) return; // 更新选中的行列 RowIndex = e.Row + 1; // 界面显示通常从1开始 ColumnIndex = e.Col + 1; // 提示用户 MessageBox.Show($"已选择基板位置: 行 {RowIndex}, 列 {ColumnIndex}", "提示", MessageBoxButton.OK, MessageBoxImage.Information); } public void MoveToSelectPad() { } } }