diff --git a/XplorePlane/ViewModels/Main/MainViewModel.cs b/XplorePlane/ViewModels/Main/MainViewModel.cs index e0cb7231..9db41b01 100644 --- a/XplorePlane/ViewModels/Main/MainViewModel.cs +++ b/XplorePlane/ViewModels/Main/MainViewModel.cs @@ -67,6 +67,7 @@ namespace XplorePlane.ViewModels.Main private SubscriptionToken _addPipelineToCncToken; private SubscriptionToken _provideCaptureTargetToken; private SubscriptionToken _roleChangedToken; + private SubscriptionToken _measurementToolToken; private PropertyChangedEventHandler _cncPropertyChangedHandler; private EventHandler _cncRunCanExecuteChangedHandler; private EventHandler _cncStopCanExecuteChangedHandler; @@ -463,6 +464,8 @@ namespace XplorePlane.ViewModels.Main _eventAggregator.GetEvent().Unsubscribe(_provideCaptureTargetToken); if (_roleChangedToken != null) _eventAggregator.GetEvent().Unsubscribe(_roleChangedToken); + if (_measurementToolToken != null) + _eventAggregator.GetEvent().Unsubscribe(_measurementToolToken); _pipelinePreviewToken = null; _whiteBackgroundRoiToken = null; @@ -470,6 +473,7 @@ namespace XplorePlane.ViewModels.Main _addPipelineToCncToken = null; _provideCaptureTargetToken = null; _roleChangedToken = null; + _measurementToolToken = null; _logger.Info("MainViewModel 资源已清理"); } @@ -642,6 +646,10 @@ namespace XplorePlane.ViewModels.Main _addPipelineToCncToken = _eventAggregator.GetEvent() .Subscribe(OnAddPipelineToCncRequested, ThreadOption.UIThread); + // 订阅 MeasurementToolEvent,接收来自 View 层的测量完成/取消通知,自动重置按钮激活状态 + _measurementToolToken = _eventAggregator.GetEvent() + .Subscribe(OnMeasurementToolEventReceived, ThreadOption.UIThread); + NavigationTree = new ObservableCollection(); NavigateHomeCommand = new DelegateCommand(OnNavigateHome); @@ -1395,9 +1403,16 @@ namespace XplorePlane.ViewModels.Main private void SetActiveMeasurementTool(MeasurementToolMode mode) { - if (_activeMeasurementToolMode == mode) return; + // 切换行为:点击已激活的工具按钮时取消激活 + if (_activeMeasurementToolMode == mode) + { + _activeMeasurementToolMode = MeasurementToolMode.None; + } + else + { + _activeMeasurementToolMode = mode; + } - _activeMeasurementToolMode = mode; RaisePropertyChanged(nameof(IsPointDistanceMeasureActive)); RaisePropertyChanged(nameof(IsPointLineDistanceMeasureActive)); RaisePropertyChanged(nameof(IsAngleMeasureActive)); @@ -1411,6 +1426,24 @@ namespace XplorePlane.ViewModels.Main SetActiveMeasurementTool(MeasurementToolMode.None); } + /// + /// 接收来自 View 层的 MeasurementToolEvent(如 MeasureCompleted 后自动重置), + /// 仅在收到 None 且当前模式非 None 时重置按钮激活状态。 + /// + private void OnMeasurementToolEventReceived(MeasurementToolMode mode) + { + // 只处理 None 通知(外部取消/完成),避免与自身发布的切换事件产生循环 + if (mode == MeasurementToolMode.None && _activeMeasurementToolMode != MeasurementToolMode.None) + { + _activeMeasurementToolMode = MeasurementToolMode.None; + RaisePropertyChanged(nameof(IsPointDistanceMeasureActive)); + RaisePropertyChanged(nameof(IsPointLineDistanceMeasureActive)); + RaisePropertyChanged(nameof(IsAngleMeasureActive)); + RaisePropertyChanged(nameof(IsThroughHoleFillRateMeasureActive)); + RaisePropertyChanged(nameof(IsBubbleMeasureActive)); + } + } + private void SetActiveBackgroundDefectMode(BackgroundDefectMode? mode) { if (_activeBackgroundDefectMode == mode) return; @@ -1440,7 +1473,7 @@ namespace XplorePlane.ViewModels.Main if (!CheckImageLoaded()) return; _logger.Info("Point distance measurement triggered."); SetActiveMeasurementTool(MeasurementToolMode.PointDistance); - _eventAggregator.GetEvent().Publish(MeasurementToolMode.PointDistance); + _eventAggregator.GetEvent().Publish(_activeMeasurementToolMode); } private void ExecutePointLineDistanceMeasure() @@ -1448,7 +1481,7 @@ namespace XplorePlane.ViewModels.Main if (!CheckImageLoaded()) return; _logger.Info("Point-line distance measurement triggered."); SetActiveMeasurementTool(MeasurementToolMode.PointLineDistance); - _eventAggregator.GetEvent().Publish(MeasurementToolMode.PointLineDistance); + _eventAggregator.GetEvent().Publish(_activeMeasurementToolMode); } private void ExecuteAngleMeasure() @@ -1456,7 +1489,7 @@ namespace XplorePlane.ViewModels.Main if (!CheckImageLoaded()) return; _logger.Info("Angle measurement triggered."); SetActiveMeasurementTool(MeasurementToolMode.Angle); - _eventAggregator.GetEvent().Publish(MeasurementToolMode.Angle); + _eventAggregator.GetEvent().Publish(_activeMeasurementToolMode); } private void ExecuteThroughHoleFillRateMeasure() @@ -1464,7 +1497,7 @@ namespace XplorePlane.ViewModels.Main if (!CheckImageLoaded()) return; _logger.Info("Through-hole fill-rate measurement triggered."); SetActiveMeasurementTool(MeasurementToolMode.ThroughHoleFillRate); - _eventAggregator.GetEvent().Publish(MeasurementToolMode.ThroughHoleFillRate); + _eventAggregator.GetEvent().Publish(_activeMeasurementToolMode); } private void ExecuteBgaDetection() @@ -1507,7 +1540,7 @@ namespace XplorePlane.ViewModels.Main // Enter bubble measurement mode. SetActiveMeasurementTool(MeasurementToolMode.BubbleMeasure); - _eventAggregator.GetEvent().Publish(MeasurementToolMode.BubbleMeasure); + _eventAggregator.GetEvent().Publish(_activeMeasurementToolMode); // Open the tool panel. _windowLauncher.ShowOrActivateVisible( diff --git a/XplorePlane/Views/Main/ViewportPanelView.xaml.cs b/XplorePlane/Views/Main/ViewportPanelView.xaml.cs index 3fc2d3d7..922bcbc9 100644 --- a/XplorePlane/Views/Main/ViewportPanelView.xaml.cs +++ b/XplorePlane/Views/Main/ViewportPanelView.xaml.cs @@ -196,6 +196,9 @@ namespace XplorePlane.Views.Main { ExecuteEdgeLineFitProcessor(args.P1, args.P2); } + + // 测量完成后自动取消激活状态,使工具栏按钮恢复默认色 + _eventAggregator?.GetEvent().Publish(MeasurementToolMode.None); } }; RoiCanvas.MeasureStatusChanged += (s, e) =>