Files

205 lines
7.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Threading.Tasks;
using Prism.Commands;
using Prism.Mvvm;
using XP.Hardware.PLC.Models;
namespace XP.Hardware.PLC.Sentry.ViewModels
{
/// <summary>
/// 单行信号 ViewModel,封装 SignalEntry 并添加运行时状态 | Single signal row ViewModel wrapping SignalEntry with runtime state
/// </summary>
public class SignalRowViewModel : BindableBase
{
private readonly SignalEntry _signal;
private string _currentValue = "--";
private bool _hasReadError;
private object _writeValue;
private string _validationError;
/// <summary>
/// 构造函数 | Constructor
/// </summary>
/// <param name="signal">信号定义条目 | Signal definition entry</param>
/// <param name="applyAction">队列写入回调 | Queue write callback</param>
/// <param name="directWriteAction">直接写入回调 | Direct write callback</param>
/// <param name="canExecuteWrite">写入命令是否可用判断 | Write command can-execute predicate</param>
public SignalRowViewModel(
SignalEntry signal,
Action<SignalRowViewModel> applyAction,
Action<SignalRowViewModel> directWriteAction,
Func<bool> canExecuteWrite)
{
_signal = signal ?? throw new ArgumentNullException(nameof(signal));
ApplyCommand = new DelegateCommand(
() => applyAction?.Invoke(this),
() => canExecuteWrite?.Invoke() ?? false);
DirectWriteCommand = new DelegateCommand(
() => directWriteAction?.Invoke(this),
() => canExecuteWrite?.Invoke() ?? false);
}
// === 信号定义信息(只读)| Signal definition info (read-only) ===
/// <summary>
/// 信号名称 | Signal name
/// </summary>
public string Name => _signal.Name;
/// <summary>
/// 数据类型 | Data type
/// </summary>
public string Type => _signal.Type;
/// <summary>
/// 起始地址 | Start address
/// </summary>
public int StartAddr => _signal.StartAddr;
/// <summary>
/// 长度/索引 | Length/Index
/// </summary>
public string IndexOrLength => _signal.IndexOrLength;
/// <summary>
/// 备注 | Remark
/// </summary>
public string Remark => _signal.Remark;
/// <summary>
/// DB 块号 | DB block number
/// </summary>
public int DBNumber => _signal.DBNumber;
/// <summary>
/// 原始信号定义条目 | Original signal definition entry
/// </summary>
public SignalEntry Signal => _signal;
/// <summary>
/// 格式化的地址显示 | Formatted address display
/// bool 类型显示位地址(DB{n}.{addr}.{bit}),其他类型显示字节地址(DB{n}.{addr}
/// </summary>
public string AddressDisplay => Type?.ToLowerInvariant() == "bool"
? $"DB{DBNumber}.{StartAddr}.{IndexOrLength}"
: $"DB{DBNumber}.{StartAddr}";
// === 运行时状态 | Runtime state ===
/// <summary>
/// 当前读取值 | Current read value
/// </summary>
public string CurrentValue
{
get => _currentValue;
set => SetProperty(ref _currentValue, value ?? "--");
}
/// <summary>
/// 是否存在读取错误 | Whether read error exists
/// </summary>
public bool HasReadError
{
get => _hasReadError;
set => SetProperty(ref _hasReadError, value);
}
/// <summary>
/// 写入值 | Write value
/// </summary>
public object WriteValue
{
get => _writeValue;
set
{
if (SetProperty(ref _writeValue, value))
{
// 写入值变更时清除校验错误 | Clear validation error when write value changes
ValidationError = null;
}
}
}
/// <summary>
/// 校验错误信息 | Validation error message
/// </summary>
public string ValidationError
{
get => _validationError;
set => SetProperty(ref _validationError, value);
}
// === 命令 | Commands ===
/// <summary>
/// 队列写入命令 | Queue write command
/// </summary>
public DelegateCommand ApplyCommand { get; }
/// <summary>
/// 直接写入+回读校验命令 | Direct write with verify command
/// </summary>
public DelegateCommand DirectWriteCommand { get; }
/// <summary>
/// 刷新写入命令可用状态 | Refresh write command can-execute state
/// </summary>
public void RefreshCommandState()
{
ApplyCommand.RaiseCanExecuteChanged();
DirectWriteCommand.RaiseCanExecuteChanged();
}
/// <summary>
/// 校验写入值是否符合信号数据类型要求 | Validate write value against signal data type
/// </summary>
/// <returns>校验错误信息,null 表示通过 | Validation error message, null means passed</returns>
public string ValidateWriteValue()
{
if (WriteValue == null)
return "写入值不能为空 | Write value cannot be empty";
var strValue = WriteValue.ToString();
if (string.IsNullOrWhiteSpace(strValue))
return "写入值不能为空 | Write value cannot be empty";
switch (Type?.ToLowerInvariant())
{
case "bool":
if (!bool.TryParse(strValue, out _))
return "布尔值仅接受 True/False | Bool accepts only True/False";
break;
case "byte":
if (!byte.TryParse(strValue, out _))
return "字节值超出范围 (0-255) | Byte value out of range (0-255)";
break;
case "short":
if (!short.TryParse(strValue, out _))
return "短整型值超出范围 | Short value out of range";
break;
case "int":
if (!int.TryParse(strValue, out _))
return "整型值超出范围 | Int value out of range";
break;
case "single":
if (!float.TryParse(strValue, out _))
return "浮点数格式错误 | Float format error";
break;
case "double":
if (!double.TryParse(strValue, out _))
return "双精度浮点数格式错误 | Double format error";
break;
case "string":
// 字符串接受任意非空值 | String accepts any non-empty value
break;
default:
return $"不支持的类型: {Type} | Unsupported type: {Type}";
}
return null;
}
}
}