243 lines
7.3 KiB
C#
243 lines
7.3 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.ComponentModel;
|
|||
|
|
using System.Windows;
|
|||
|
|
using System.Windows.Controls;
|
|||
|
|
using System.Windows.Media;
|
|||
|
|
|
|||
|
|
namespace WpfApp.src.components
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// SensorChart.xaml 的交互逻辑
|
|||
|
|
/// </summary>
|
|||
|
|
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<double>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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<double>), typeof(SensorChart),
|
|||
|
|
new PropertyMetadata(new List<double>(), OnRedLineValuesChanged));
|
|||
|
|
|
|||
|
|
public List<double> RedLineValues
|
|||
|
|
{
|
|||
|
|
get { return (List<double>)GetValue(RedLineValuesProperty); }
|
|||
|
|
set { SetValue(RedLineValuesProperty, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static void OnRedLineValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|||
|
|
{
|
|||
|
|
var control = d as SensorChart;
|
|||
|
|
control?.UpdateRedLinePositions();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#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<double> _redLinePositions = new List<double>();
|
|||
|
|
public List<double> RedLinePositions
|
|||
|
|
{
|
|||
|
|
get { return _redLinePositions; }
|
|||
|
|
private set
|
|||
|
|
{
|
|||
|
|
_redLinePositions = value;
|
|||
|
|
OnPropertyChanged(nameof(RedLinePositions));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 私有方法
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 将数值转换为Y坐标位置
|
|||
|
|
/// 刻度范围:40 到 -40,对应Y坐标:20 到 420
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="value">数值</param>
|
|||
|
|
/// <returns>Y坐标</returns>
|
|||
|
|
private double ValueToY(double value)
|
|||
|
|
{
|
|||
|
|
// 限制数值范围
|
|||
|
|
value = Math.Max(-40, Math.Min(40, value));
|
|||
|
|
|
|||
|
|
// 线性映射:40对应Y=20,-40对应Y=420
|
|||
|
|
// Y = 220 - value * 5
|
|||
|
|
return 220 - value * 5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 更新柱状图位置
|
|||
|
|
/// </summary>
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 更新红线位置
|
|||
|
|
/// </summary>
|
|||
|
|
private void UpdateRedLinePositions()
|
|||
|
|
{
|
|||
|
|
var positions = new List<double>();
|
|||
|
|
if (RedLineValues != null)
|
|||
|
|
{
|
|||
|
|
foreach (var value in RedLineValues)
|
|||
|
|
{
|
|||
|
|
positions.Add(ValueToY(value));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
RedLinePositions = positions;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 公共方法
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 设置传感器数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="name">传感器名称</param>
|
|||
|
|
/// <param name="value">数值</param>
|
|||
|
|
/// <param name="redLines">红线数值列表</param>
|
|||
|
|
/// <param name="headerColor">标题背景色</param>
|
|||
|
|
public void SetSensorData(string name, double value, List<double> redLines = null, Color? headerColor = null)
|
|||
|
|
{
|
|||
|
|
SensorName = name;
|
|||
|
|
Value = value;
|
|||
|
|
|
|||
|
|
if (redLines != null)
|
|||
|
|
{
|
|||
|
|
RedLineValues = new List<double>(redLines);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (headerColor.HasValue)
|
|||
|
|
{
|
|||
|
|
HeaderBackground = new SolidColorBrush(headerColor.Value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 添加红线
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="value">红线数值</param>
|
|||
|
|
public void AddRedLine(double value)
|
|||
|
|
{
|
|||
|
|
var lines = new List<double>(RedLineValues) { value };
|
|||
|
|
RedLineValues = lines;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 清除所有红线
|
|||
|
|
/// </summary>
|
|||
|
|
public void ClearRedLines()
|
|||
|
|
{
|
|||
|
|
RedLineValues = new List<double>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
}
|