将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。

This commit is contained in:
QI Mingxuan
2026-04-16 17:31:13 +08:00
parent 6ec4c3ddaa
commit 2bd6e566c3
581 changed files with 74600 additions and 222 deletions
@@ -0,0 +1,204 @@
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;
}
}
}