using System.Collections.ObjectModel; using System.IO.Ports; using System.Linq; using System.Windows.Input; using UIShare.PubEvent; using UIShare.UIViewModel; using UIShare.ViewModelBase; namespace SettingModule.ViewModels.Dialogs { /// /// 串口连接配置对话框 VM。 /// 通过 DialogParameters 接收宿主 DeviceInfoModel;保存时把副本写回宿主。 /// public class SerialPortConfigViewModel : DialogViewModelBase { #region 属性 private string _title = "串口连接配置"; public string Title { get => _title; set => SetProperty(ref _title, value); } private SerialPortConnectionConfig _config = new(); public SerialPortConnectionConfig Config { get => _config; set => SetProperty(ref _config, value); } /// 当前可用串口列表(OnDialogOpened 刷新)。 public ObservableCollection AvailablePorts { get; } = new(); public ObservableCollection CommonBaudRates { get; } = new() { 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }; public ObservableCollection DataBitsList { get; } = new() { 5, 6, 7, 8 }; public ObservableCollection StopBitsList { get; } = new() { "One", "OnePointFive", "Two" }; public ObservableCollection ParityList { get; } = new() { "None", "Odd", "Even", "Mark", "Space" }; public ObservableCollection CommonTimeouts { get; } = new() { 500, 1000, 2000, 3000, 5000, 10000 }; private string _errorMessage = string.Empty; public string ErrorMessage { get => _errorMessage; set => SetProperty(ref _errorMessage, value); } #endregion #region 命令 public ICommand SaveCommand { get; } public ICommand CancelCommand { get; } public ICommand RefreshPortsCommand { get; } #endregion private DeviceInfoModel? _hostDevice; public SerialPortConfigViewModel(IContainerProvider containerProvider) : base(containerProvider) { SaveCommand = new DelegateCommand(OnSave); CancelCommand = new DelegateCommand(OnCancel); RefreshPortsCommand = new DelegateCommand(RefreshPorts); } private void RefreshPorts() { AvailablePorts.Clear(); // 若当前选中的串口不在可用列表中,仍保留显示,便于离线编辑 if (!string.IsNullOrEmpty(Config.PortName) && !AvailablePorts.Contains(Config.PortName)) AvailablePorts.Insert(0, Config.PortName); } private bool Validate(out string error) { error = string.Empty; if (string.IsNullOrWhiteSpace(Config.PortName)) { error = "串口名称不能为空"; return false; } if (Config.BaudRate <= 0) { error = "波特率必须大于 0"; return false; } if (Config.DataBits < 5 || Config.DataBits > 8) { error = "数据位必须在 5 - 8 之间"; return false; } if (Config.ReadTimeout < 0 || Config.WriteTimeout < 0) { error = "超时时间不能为负数"; return false; } return true; } private void OnSave() { if (!Validate(out var error)) { ErrorMessage = error; return; } ErrorMessage = string.Empty; if (_hostDevice != null) { _hostDevice.SerialPortConfig ??= new SerialPortConnectionConfig(); Config.CopyTo(_hostDevice.SerialPortConfig); _hostDevice.ConnectionType = "Serial"; } RequestClose.Invoke(ButtonResult.OK); } private void OnCancel() => RequestClose.Invoke(ButtonResult.Cancel); #region Prism Dialog 规范 public override void OnDialogOpened(IDialogParameters parameters) { _eventAggregator.GetEvent().Publish(true); if (parameters.ContainsKey("Device")) { _hostDevice = parameters.GetValue("Device"); Title = $"串口连接配置 - {_hostDevice?.DeviceName}"; Config = new SerialPortConnectionConfig(_hostDevice?.SerialPortConfig); } else if (parameters.ContainsKey("Config")) { Config = new SerialPortConnectionConfig(parameters.GetValue("Config")); } RefreshPorts(); } public override void OnDialogClosed() { _eventAggregator.GetEvent().Publish(false); } #endregion } }