using JM1.VisionModule; using MainShell.AlgorithmCalib.Model; using MainShell.AlgorithmCalib.Service; using MainShell.AlgorithmCalib.View; using MainShell.Common; using MainShell.Common.Display.ViewModel; using MainShell.Filewritable; using MainShell.Hardware; using MaxwellFramework.Core.Interfaces; using MwFramework.Controls.SystemCalib; using MwFramework.ManagerService; using Stylet; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Xml; using Point = SemiconductorVisionAlgorithm.SemiParams.Point; namespace MainShell.AlgorithmCalib.ViewModel { public class FusionMenuCalibViewModel : Screen, IPage { private readonly Dictionary _calibWindows = new Dictionary(); private List _calibResultRealPoint = new List(); private List _calibResultAxisPoint = new List(); private MotionFusion _motionFusion = new MotionFusion(); private FusionCalibMotionService _fusionCalibMotionService; public string Name { get; set; } = "FusionMenuCalib"; public string CalibName { get; set; } public string FileSaveDir { get; set; } private bool _isDataLoaded = false; private CameraAxisViewModel _cameraAxisViewModelSevice = new CameraAxisViewModel(); public CameraAxisViewModel CameraAxisViewModelSevice { get { return _cameraAxisViewModelSevice; } set { _cameraAxisViewModelSevice = value; OnPropertyChanged(nameof(CameraAxisViewModelSevice)); } } private ObservableCollection _fusionCalibParItem = new ObservableCollection(); public ObservableCollection FusionCalibParItem { get { return _fusionCalibParItem; } set { _fusionCalibParItem = value; OnPropertyChanged(nameof(FusionCalibParItem)); } } private FusionCalibParItem _selectedCalibPar; public FusionCalibParItem SelectedCalibPar { get { return _selectedCalibPar; } set { _selectedCalibPar = value; OnPropertyChanged(nameof(SelectedCalibPar)); } } private FusionCalibParItem _inputParam; public FusionCalibParItem InputParam { get { return _inputParam; } set { SetAndNotify(ref _inputParam, value); } } private FusionCalibParItem _resultParam; public FusionCalibParItem ResultParam { get { return _resultParam; } set { SetAndNotify(ref _resultParam, value); } } private List _hardwareDevice; public List HardwareDevice { get { return _hardwareDevice; } set { _hardwareDevice = value; NotifyOfPropertyChange(); } } private HardwareManager _hardware; public HardwareManager Hardware { get { return _hardware; } set { _hardware = value; NotifyOfPropertyChange(); } } private bool _isCalibFinished; public bool IsCalibFinished { get { return _isCalibFinished; } set { SetAndNotify(ref _isCalibFinished, value); } } /// /// 无参构造函数 /// public FusionMenuCalibViewModel() { } /// /// 手动创建时使用的静态工厂方法 /// /// 相机名称,如 "BottomCamera" /// 对应的硬件设备 public static FusionMenuCalibViewModel Create(string calibName, string fileSaveName, List device, HardwareManager hardware, FusionCalibMotionService motion) { var vm = new FusionMenuCalibViewModel(); vm.Initialize(calibName, fileSaveName, device, hardware, motion); return vm; } protected override void OnViewLoaded() { base.OnViewLoaded(); if (_hardware != null) { _cameraAxisViewModelSevice = new CameraAxisViewModel(); _cameraAxisViewModelSevice.CameraAxisDevices.HardwareDeviceList = HardwareDevice; NotifyOfPropertyChange(nameof(CameraAxisViewModel)); } if (!_isDataLoaded) { ReadCalibData(); _isDataLoaded = true; } } private void Initialize(string calibName, string fileSaveName, List device, HardwareManager hardware, FusionCalibMotionService motion) { CalibName = calibName; Hardware = hardware; HardwareDevice = device; _fusionCalibMotionService = motion; FileSaveDir = Path.Combine(Paths.CalibSettingPath, "fusionCalib"); var paramList = IoC.Get() as IParamList; } public void btnOpenCalibWindow() { if (SelectedCalibPar == null) { MwMessageBox.Show("请先选择一组标定数据。", "提示", MessageBoxButton.OK, MessageBoxImage.Information); return; } string cameraId = SelectedCalibPar.Camera_ID; // ── 如果已有缓存窗口,直接激活显示 ── if (_calibWindows.TryGetValue(cameraId, out var existingWindow)) { if (existingWindow.WindowState == WindowState.Minimized) existingWindow.WindowState = WindowState.Normal; existingWindow.Show(); existingWindow.Activate(); return; } var calibVM = CameraFusionPadCalibViewModel.Create("", CalibName, HardwareDevice, SelectedCalibPar, Hardware, _fusionCalibMotionService); calibVM.FileSaveDir = this.FileSaveDir; // ② 创建视图 var calibView = new CameraFusionPadCalibView { DataContext = calibVM, }; // 4. 创建 Window 包裹这个 UserControl var window = new Window { Title = $"融合标定-{cameraId}", Width = 1100, Height = 750, WindowStartupLocation = WindowStartupLocation.CenterOwner, Owner = Application.Current.MainWindow, ResizeMode = ResizeMode.CanResize, Content = calibView }; // ── 拦截关闭:改为隐藏,保留内存状态 ── window.Closing += (s, args) => { args.Cancel = true; // 取消真正的关闭 window.Hide(); // 仅隐藏,VM 和 View 状态全部保留 }; // ── 用 Unloaded 代替 Closed 做数据同步 ── // 每次隐藏时都把 Service 最新数据写回选中行 window.IsVisibleChanged += (s, args) => { if (!(bool)args.NewValue) // 变为不可见(Hide) { SyncCalibResultBack(calibVM); } }; // 缓存 _calibWindows[cameraId] = window; window.Show(); window.Closed += (s, args) => { var innerData = calibVM.FusionCalibParItem; if (innerData != null) { SelectedCalibPar.Index = innerData.Index; SelectedCalibPar.MoveAxisPos = innerData.MoveAxisPos; SelectedCalibPar.ApproachXPos = innerData.ApproachXPos; SelectedCalibPar.ApproachYPos = innerData.ApproachYPos; SelectedCalibPar.StartX = innerData.StartX; SelectedCalibPar.StartY = innerData.StartY; SelectedCalibPar.Step = innerData.Step; SelectedCalibPar.Count = innerData.Count; SelectedCalibPar.RulerPoints = innerData.RulerPoints; SelectedCalibPar.RealPoints = innerData.RealPoints; // 刷新 DataGrid OnPropertyChanged(nameof(FusionCalibParItem)); } }; } /// /// 将内部标定窗口的最新数据同步回外部 DataGrid 选中行 /// private void SyncCalibResultBack(CameraFusionPadCalibViewModel calibVM) { var innerData = calibVM.ResultParam; if (innerData != null) return; var target = FusionCalibParItem.FirstOrDefault(p => p.Camera_ID == calibVM.CameraName); if(target == null) return; target.Index = innerData.Index; target.MoveAxisPos = innerData.MoveAxisPos; target.ApproachXPos = innerData.ApproachXPos; target.ApproachYPos = innerData.ApproachYPos; target.StartX = innerData.StartX; target.StartY = innerData.StartY; target.Step = innerData.Step; target.Count = innerData.Count; target.RulerPoints = innerData.RulerPoints; target.RealPoints = innerData.RealPoints; // 刷新 DataGrid OnPropertyChanged(nameof(FusionCalibParItem)); } public void btnReadCalibData() { var result = MwMessageBox.Show($"确认读取本地标定数据?", "确认读取", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) { if (!ReadCalibData()) { MwMessageBox.Show("读取本地标定数据失败!", "提示", MessageBoxButton.OK, MessageBoxImage.Error); } } } public bool ReadCalibData() { try { var paramList = IoC.Get() as IParamList; //FusionCalibParItem.CalibParList = new ObservableCollection(); for (int i = 0; i < 4; i++) { var filePath = Path.Combine(FileSaveDir, $"Fusion_Time{i + 1}.xml"); var pointsFilePath = Path.Combine(FileSaveDir, $"Fusion_Time{i + 1}.txt"); bool hasXml = File.Exists(filePath); bool hasTxt = File.Exists(pointsFilePath); double moveAxisPos = 0; double approachXPos = 0; double approachYPos = 0; double startX = 0; double startY = 0; double step = 0; int count = 0; List rulerPoints = new List(); List realPoints = new List(); // ① 有 XML → 读取参数 if (hasXml) { //var uiData = UIDataManager.Instance.GetUIData(paramList); //uiData.Read(filePath); //var xmlData=XmlReader(filePath); //if (xmlData.Datas != null && xmlData.Datas.Count > 0) //{ // var item = xmlData.Datas[0]; // 每个文件只有一组数据 // index=item.Index; // moveAxisPos = item.MoveAxisPos; // approachXPos = item.ApproachXPos; // approachYPos = item.ApproachYPos; // startX = item.StartX; // startY = item.StartY; // step = item.Step; // count = item.Count; //} } // ② 有 TXT → 读取标定点位 if (hasTxt) { MotionCalibFileService.ReadCalibPointsFile( pointsFilePath, out realPoints, out rulerPoints); rulerPoints = rulerPoints ?? new List(); realPoints = realPoints ?? new List(); } // ③ 无论什么情况,都加到列表(保证 5 组都在) var par = new FusionCalibParItem { Index = i + 1, Camera_ID = "Fusion_Time" + (i + 1), MoveAxisPos = moveAxisPos, ApproachXPos = approachXPos, ApproachYPos = approachYPos, StartX = startX, StartY = startY, Step = step, Count = count, RulerPoints = rulerPoints, RealPoints = realPoints, }; FusionCalibParItem.Add(par); } return true; } catch { return false; } } public void btnApplyCalibData() { //if (FusionCalibParItem.CalibParList.Count != 5) //{ // MwMessageBox.Show("标定数据不足,请完成全部标定!", "提示", MessageBoxButton.OK, MessageBoxImage.Error); // return; //} //var result = MwMessageBox.Show($"确认应用标定数据?", "确认应用", MessageBoxButton.YesNo, MessageBoxImage.Warning); //if (result == MessageBoxResult.Yes) //{ // if (true) // // { // MwMessageBox.Show("应用标定数据成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); // } //} } public void ApplayCalibData() { //List cameraIdList = new List(); //for (int i = 0; i < 5; i++) //{ // var resultPointsList = FusionCalibParItem.CalibParList[i]; // _motionFusion.Set(i, resultPointsList.ResultRealPoints, resultPointsList.ResultAxisPoints); // cameraIdList.Add(resultPointsList.CameraId); //} //_motionFusion.AutoSelectPt(cameraIdList[0], cameraIdList[1], cameraIdList[2], cameraIdList[3], out _calibResultRealPoint, out _calibResultAxisPoint); //MwAlgorithmHelper.Instance.RulerToRealMaritex("topCameraPad", _calibResultAxisPoint, _calibResultRealPoint, 1, 1, 1, 1, UIDataManager.CalibDataDir); } public void XmlReader(string xmlFilePath) { } } }