using System; using System.ComponentModel; using System.Threading.Tasks; using Prism.Commands; using Prism.Mvvm; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; namespace TeamAAS_VP.Core.Robots { /// /// Axis view-model for binding to View: provides Axis + / - commands, axis name and current position. /// public class AxisViewModel : BindableBase, IDisposable { private readonly IRobot _robot; private readonly string _axisName; private double _currentPosition; private double _step; public DelegateCommand AxisPlusCommand { get; private set; } public DelegateCommand AxisMinusCommand { get; private set; } /// /// 轴名称(X/Y/Z/U) /// public string AxisName => _axisName; /// /// 当前轴位置(从 Robot 读取或命令后更新) /// public double CurrentPosition { get => _currentPosition; private set => SetProperty(ref _currentPosition, value); } /// /// 每次 jog 的步长(可设置) /// public double Step { get => _step; set { if (SetProperty(ref _step, value)) { RaiseCanExecuteChanged(); } } } public AxisViewModel(string axisName, IRobot robot, double step = 1.0) { if (string.IsNullOrWhiteSpace(axisName)) throw new ArgumentNullException(nameof(axisName)); _axisName = axisName.ToUpper(); _robot = robot ?? throw new ArgumentNullException(nameof(robot)); _step = step; AxisPlusCommand = DelegateCommand.FromAsyncHandler(ExecutePlusAsync, CanExecuteCommands); AxisMinusCommand = DelegateCommand.FromAsyncHandler(ExecuteMinusAsync, CanExecuteCommands); // 尝试初始化当前位置(异步,不阻塞构造) Task.Run(async () => await UpdatePositionFromRobotAsync()); // 订阅机器人属性变化以刷新命令可用性 if (_robot is INotifyPropertyChanged npc) { npc.PropertyChanged += Robot_PropertyChanged; } } private void Robot_PropertyChanged(object sender, PropertyChangedEventArgs e) { // 监听 CanExecute 或 IsConnected 等关键属性名(Robots 中使用 CanExecute 字段) if (string.Equals(e.PropertyName, nameof(XYZU_Robot.CanExecute), StringComparison.OrdinalIgnoreCase) || string.Equals(e.PropertyName, nameof(IRobot.CanExecute), StringComparison.OrdinalIgnoreCase) || string.Equals(e.PropertyName, nameof(IRobot.IsConnected), StringComparison.OrdinalIgnoreCase)) { RaiseCanExecuteChanged(); } } private bool CanExecuteCommands() { try { if (_robot == null) return false; // 优先使用机器人公开的 CanExecute 属性(若存在),否则回退到 IsConnected var canExecuteProp = _robot.GetType().GetProperty("CanExecute"); if (canExecuteProp != null && canExecuteProp.PropertyType == typeof(bool)) { return (bool)canExecuteProp.GetValue(_robot); } return _robot.IsConnected; } catch { return false; } } private void RaiseCanExecuteChanged() { AxisPlusCommand.RaiseCanExecuteChanged(); AxisMinusCommand.RaiseCanExecuteChanged(); } private async Task ExecutePlusAsync() { if (!CanExecuteCommands()) return; try { await _robot.JogAsync(_axisName, Step); } catch { // 忽略错误,视需求可扩展日志或通知 } await UpdatePositionFromRobotAsync(); } private async Task ExecuteMinusAsync() { if (!CanExecuteCommands()) return; try { await _robot.JogAsync(_axisName, -Step); } catch { // 忽略错误 } await UpdatePositionFromRobotAsync(); } /// /// 从 Robot 读取完整位置并更新当前轴的 CurrentPosition /// public async Task UpdatePositionFromRobotAsync() { try { var pos = await _robot.GetRobotPosAsync(); if (pos == null) return; switch (_axisName) { case "X": CurrentPosition = pos.X; break; case "Y": CurrentPosition = pos.Y; break; case "Z": CurrentPosition = pos.Z; break; case "U": CurrentPosition = pos.U; break; default: // 未知轴,保持不变 break; } } catch { // 忽略读取错误 } } public void Dispose() { if (_robot is INotifyPropertyChanged npc) { npc.PropertyChanged -= Robot_PropertyChanged; } } } }