using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace WpfApp.src.components; /// /// 刻度线数据结构 /// public class ScaleLine { public double Y1 { get; set; } public double Y2 { get; set; } public double X1 { get; set; } public double X2 { get; set; } public double StrokeThickness { get; set; } public string Label { get; set; } public double LabelX { get; set; } public double LabelY { get; set; } public bool IsMainScale { get; set; } } /// /// SensorChart.xaml 的交互逻辑 /// public partial class SensorChart : UserControl, INotifyPropertyChanged { public SensorChart() { InitializeComponent(); DataContext = this; // 设置默认值 SensorName = "传感器"; HeaderBackground = new SolidColorBrush(Color.FromRgb(230, 243, 255)); // #E6F3FF Value = 0; RedLineValues = new List(); Level = SensorLevel.Medium; // 默认中等 // 生成初始刻度 GenerateScaleLines(); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #region 依赖属性 // 传感器名称 public static readonly DependencyProperty SensorNameProperty = DependencyProperty.Register("SensorName", typeof(string), typeof(SensorChart), new PropertyMetadata("传感器", OnSensorNameChanged)); public string SensorName { get { return (string)GetValue(SensorNameProperty); } set { SetValue(SensorNameProperty, value); } } private static void OnSensorNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as SensorChart; control?.OnPropertyChanged(nameof(SensorName)); } // 标题背景色 public static readonly DependencyProperty HeaderBackgroundProperty = DependencyProperty.Register("HeaderBackground", typeof(Brush), typeof(SensorChart), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(230, 243, 255)), OnHeaderBackgroundChanged)); public Brush HeaderBackground { get { return (Brush)GetValue(HeaderBackgroundProperty); } set { SetValue(HeaderBackgroundProperty, value); } } private static void OnHeaderBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as SensorChart; control?.OnPropertyChanged(nameof(HeaderBackground)); } // 数值 public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(SensorChart), new PropertyMetadata(0.0, OnValueChanged)); public double Value { get { return (double)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as SensorChart; control?.UpdateBarPosition(); } // 红线数值列表 public static readonly DependencyProperty RedLineValuesProperty = DependencyProperty.Register("RedLineValues", typeof(List), typeof(SensorChart), new PropertyMetadata(new List(), OnRedLineValuesChanged)); public List RedLineValues { get { return (List)GetValue(RedLineValuesProperty); } set { SetValue(RedLineValuesProperty, value); } } private static void OnRedLineValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as SensorChart; control?.UpdateRedLinePositions(); } // 传感器等级 public static readonly DependencyProperty LevelProperty = DependencyProperty.Register("Level", typeof(SensorLevel), typeof(SensorChart), new PropertyMetadata(SensorLevel.Medium, OnLevelChanged)); public SensorLevel Level { get { return (SensorLevel)GetValue(LevelProperty); } set { SetValue(LevelProperty, value); } } private static void OnLevelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as SensorChart; control?.OnLevelChanged(); } #endregion #region 计算属性 private double _barTop; public double BarTop { get { return _barTop; } private set { _barTop = value; OnPropertyChanged(nameof(BarTop)); } } private double _barHeight; public double BarHeight { get { return _barHeight; } private set { _barHeight = value; OnPropertyChanged(nameof(BarHeight)); } } private List _redLinePositions = new List(); public List RedLinePositions { get { return _redLinePositions; } private set { _redLinePositions = value; OnPropertyChanged(nameof(RedLinePositions)); } } private List _scaleLines = new List(); public List ScaleLines { get { return _scaleLines; } private set { _scaleLines = value; OnPropertyChanged(nameof(ScaleLines)); } } // 当前等级的最小值 public double MinValue { get { switch (Level) { case SensorLevel.Low: return -20; case SensorLevel.Medium: return -40; case SensorLevel.High: return -60; default: return -40; } } } // 当前等级的最大值 public double MaxValue { get { switch (Level) { case SensorLevel.Low: return 20; case SensorLevel.Medium: return 40; case SensorLevel.High: return 60; default: return 40; } } } #endregion #region 私有方法 /// /// 等级改变时的处理 /// private void OnLevelChanged() { OnPropertyChanged(nameof(Level)); OnPropertyChanged(nameof(MinValue)); OnPropertyChanged(nameof(MaxValue)); GenerateScaleLines(); UpdateBarPosition(); UpdateRedLinePositions(); } /// /// 生成刻度线 /// private void GenerateScaleLines() { var lines = new List(); double minVal = MinValue; double maxVal = MaxValue; // 根据等级确定刻度间隔 double mainInterval = (maxVal - minVal) / 8; // 8个主刻度间隔 double subInterval = mainInterval / 4; // 每个主刻度间隔4个小刻度 // 生成主刻度线 for (int i = 0; i <= 8; i++) { double value = maxVal - i * mainInterval; double y = ValueToY(value); lines.Add(new ScaleLine { X1 = 40, Y1 = y, X2 = 130, Y2 = y, StrokeThickness = 1, Label = value.ToString("0"), LabelX = 135, LabelY = y - 5, IsMainScale = true }); // 生成小刻度线(除了最后一个主刻度) if (i < 8) { for (int j = 1; j < 4; j++) { double subValue = value - j * subInterval; double subY = ValueToY(subValue); lines.Add(new ScaleLine { X1 = 40, Y1 = subY, X2 = 125, Y2 = subY, StrokeThickness = 0.5, Label = "", LabelX = 0, LabelY = 0, IsMainScale = false }); } } } ScaleLines = lines; } /// /// 将数值转换为Y坐标位置 /// 根据当前等级动态计算刻度范围 /// /// 数值 /// Y坐标 private double ValueToY(double value) { double minVal = MinValue; double maxVal = MaxValue; // 限制数值范围 value = Math.Max(minVal, Math.Min(maxVal, value)); // 线性映射:maxVal对应Y=20,minVal对应Y=420 double range = maxVal - minVal; return 220 - ((value - minVal) / range - 0.5) * 400; } /// /// 更新柱状图位置 /// private void UpdateBarPosition() { if (Value >= 0) { // 正值:从0线向上 BarTop = ValueToY(Value); BarHeight = ValueToY(0) - ValueToY(Value); } else { // 负值:从0线向下 BarTop = ValueToY(0); BarHeight = ValueToY(Value) - ValueToY(0); } } /// /// 更新红线位置 /// private void UpdateRedLinePositions() { var positions = new List(); if (RedLineValues != null) { foreach (var value in RedLineValues) { positions.Add(ValueToY(value)); } } RedLinePositions = positions; } #endregion #region 公共方法 /// /// 设置传感器数据 /// /// 传感器名称 /// 数值 /// 红线数值列表 /// 标题背景色 /// 传感器等级 public void SetSensorData(string name, double value, List redLines = null, Color? headerColor = null, SensorLevel? level = null) { SensorName = name; Value = value; if (redLines != null) { RedLineValues = new List(redLines); } if (headerColor.HasValue) { HeaderBackground = new SolidColorBrush(headerColor.Value); } if (level.HasValue) { Level = level.Value; } } /// /// 添加红线 /// /// 红线数值 public void AddRedLine(double value) { var lines = new List(RedLineValues) { value }; RedLineValues = lines; } /// /// 清除所有红线 /// public void ClearRedLines() { RedLineValues = new List(); } #endregion } /// /// 传感器等级枚举 /// public enum SensorLevel { Low, // 低等:-20到20 Medium, // 中等:-40到40 High // 高等:-60到60 }