165 lines
6.4 KiB
C#
165 lines
6.4 KiB
C#
using Prism.Mvvm;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace CapMachine.Wpf.CanDrive
|
||
{
|
||
/// <summary>
|
||
/// Dbc 信息
|
||
/// </summary>
|
||
public class CanDbcModel : BindableBase
|
||
{
|
||
/// <summary>
|
||
/// 消息Id
|
||
/// </summary>
|
||
public string? MsgId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 配置的中文名称:速度,转速限制,使能等常用的信息数据
|
||
/// 但不是所有的SignalName都会配置一个Name,只是需要时才会配置名称
|
||
/// 但是CanDbcModel集合会包括所有的SignalName名称的
|
||
/// </summary>
|
||
private string? _name;
|
||
|
||
/// <summary>
|
||
/// 配置的中文名称:速度,转速限制,使能等常用的信息数据
|
||
/// 但不是所有的SignalName都会配置一个Name,只是需要时才会配置名称
|
||
/// 但是CanDbcModel集合会包括所有的SignalName名称的
|
||
/// </summary>
|
||
public string? Name
|
||
{
|
||
get { return _name; }
|
||
set
|
||
{
|
||
if (_name != value)
|
||
{
|
||
_name = value;
|
||
RaisePropertyChanged();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 消息名称
|
||
/// </summary>
|
||
public string? MsgName { get; set; }
|
||
|
||
/// <summary>
|
||
/// 信号名称
|
||
/// </summary>
|
||
public string? SignalName { get; set; }
|
||
|
||
/// <summary>
|
||
/// 信号描述
|
||
/// </summary>
|
||
public string? SignalDesc { get; set; }
|
||
|
||
/// <summary>
|
||
/// 信号单位
|
||
/// </summary>
|
||
public string? SignalUnit { get; set; }
|
||
|
||
|
||
private string? _SignalRtValue = "--";
|
||
/// <summary>
|
||
/// 信号实时值(供 UI 绑定显示)。
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// - 仅当文本发生变化时才触发通知,避免无谓 UI 刷新。
|
||
/// - 若期望进一步降低分配开销,建议在调用方(接收循环)先做“数值层去重”,
|
||
/// 即:仅在数值变化(可设置容差)时才调用 ToString() 格式化并赋值到本属性。
|
||
/// 这样可以显著减少字符串分配与 GC 压力。
|
||
/// </remarks>
|
||
/// <example>
|
||
/// // 示例:数值层去重后再格式化(接收循环中使用)
|
||
/// // if (Math.Abs(newVal - lastVal) > 1e-3) { model.SignalRtValue = newVal.ToString("F3"); lastVal = newVal; }
|
||
/// </example>
|
||
public string? SignalRtValue
|
||
{
|
||
get { return _SignalRtValue; }
|
||
set
|
||
{
|
||
if (_SignalRtValue != value)
|
||
{
|
||
_SignalRtValue = value;
|
||
RaisePropertyChanged();
|
||
}
|
||
}
|
||
}
|
||
|
||
private StringBuilder _SignalRtValueSb = new StringBuilder(16);
|
||
/// <summary>
|
||
/// 信号实时值的可变文本缓冲接口。
|
||
/// 设计目的:
|
||
/// - 避免外部传入的 StringBuilder 被直接保存(引用别名问题),统一复制文本到内部缓冲 _SignalRtValueSb;
|
||
/// - 仅当文本内容变化时才更新 SignalRtValue 并 RaisePropertyChanged,减少 UI 抖动与无谓刷新;
|
||
/// - 对 value == null 做防御:清空内部缓冲并置空显示文本(如需显示 “--” 可按需替换)。
|
||
/// 使用方式:
|
||
/// - 接收环路可重复复用同一个外部 StringBuilder 作为临时缓存,调用本属性进行更新不会产生实例共享风险。
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 注意事项:
|
||
/// 1) 本属性会复制文本,不会保存外部 StringBuilder 引用;这可避免多个模型共享同一实例导致的数据串扰和并发问题。
|
||
/// 2) 若你的 UI 需要统一的“空值占位符”,可将 setter 中的空字符串替换为 "--",与字段初始值保持一致。
|
||
/// 3) 线程模型:建议仍在 UI 线程更新以避免跨线程通知问题;如需后台线程更新,请确保有合适的调度(Dispatcher/同步上下文)。
|
||
/// 4) 性能建议:结合 SignalRtValue 的备注,在进入本 setter 前尽量做数值层去重,进一步减少字符串分配。
|
||
/// </remarks>
|
||
/// <example>
|
||
/// // 示例:接收循环中复用临时缓存
|
||
/// // var tmp = new StringBuilder(32);
|
||
/// // ... 填充 tmp ...
|
||
/// // model.SignalRtValueSb = tmp; // 本属性会复制 tmp 的内容,安全且不会产生实例共享
|
||
/// </example>
|
||
public StringBuilder SignalRtValueSb
|
||
{
|
||
get { return _SignalRtValueSb; }
|
||
set
|
||
{
|
||
// 防御:若外部传入 null,清空内部状态并复位显示文本
|
||
// 注意:此处将显示文本设为空字符串 "",如果希望与初始占位符 "--" 一致,可改为 SignalRtValue = "--"。
|
||
if (value == null)
|
||
{
|
||
if (_SignalRtValue != string.Empty)
|
||
{
|
||
_SignalRtValueSb.Clear();
|
||
SignalRtValue = string.Empty;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 复制策略:不保存外部 StringBuilder 的引用,改为复制其当前文本内容
|
||
// 这样可避免多个模型共享同一 StringBuilder 实例导致的数据串扰与线程安全问题
|
||
var str = value.ToString();
|
||
// 仅当文本内容确实发生变化时,才更新内部缓冲与绑定属性,减少无谓的 UI 刷新与字符串分配
|
||
if (!string.Equals(_SignalRtValue, str, StringComparison.Ordinal))
|
||
{
|
||
_SignalRtValueSb.Clear();
|
||
_SignalRtValueSb.Append(str);
|
||
SignalRtValue = str;
|
||
}
|
||
}
|
||
}
|
||
|
||
private int _IsSeletedInfo;
|
||
/// <summary>
|
||
/// 被选中的信息
|
||
/// 方便标注着色
|
||
/// </summary>
|
||
public int IsSeletedInfo
|
||
{
|
||
get { return _IsSeletedInfo; }
|
||
set { _IsSeletedInfo = value; RaisePropertyChanged(); }
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 发布者
|
||
/// </summary>
|
||
public string? Publisher { get; set; }
|
||
|
||
}
|
||
}
|