This commit is contained in:
YONGYE 2025-10-11 15:36:43 +08:00
parent 18a63a1c1d
commit 0a2798497f
5 changed files with 757 additions and 814 deletions

View File

@ -4,442 +4,296 @@ using LiveCharts.Wpf;
using SqlSugar; using SqlSugar;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Navigation; using System.Windows.Navigation;
using WpfApp.src.components; using WpfApp.src.components;
using WpfApp.src.config;
using WpfApp.src.view; using WpfApp.src.view;
using WpfApp.Utils;
namespace WpfApp namespace WpfApp;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{ {
/// <summary> private readonly LogService log;
/// Interaction logic for MainWindow.xaml private readonly DatabaseService db;
/// </summary> private readonly EventService<GeneralEventArgs> even;
public partial class MainWindow : Window
public MainWindow(LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService)
{ {
private readonly LogService log; InitializeComponent();
private readonly DatabaseService db;
private readonly EventService<GeneralEventArgs> even;
public MainWindow(LogService logService, DatabaseService databaseService, EventService<GeneralEventArgs> eventService) log = logService;
db = databaseService;
even = eventService;
// 记录窗口初始化日志
log.Info("MainWindow", "主窗口已通过依赖注入初始化");
log.Info("窗体启动");
even.AddEventHandler("GeneralEvent", (m, d) =>
{ {
InitializeComponent(); log.Info($"接收到事件:{d.Data}");
});
SetWindowTitle("FMSDGAUGE");
log = logService; var labels = new[] { "13:27 23", "13:27 45", "13:27 49", "13:27 50", "13:27 55" };
db = databaseService;
even = eventService;
// 记录窗口初始化日志 var config1 = new ChartConfig
log.Info("MainWindow", "主窗口已通过依赖注入初始化");
log.Info("窗体启动");
even.AddEventHandler("GeneralEvent", (m, d) =>
{
log.Info($"接收到事件:{d.Data}");
});
#region 线
SetWindowTitle("FMSDGAUGE");
// 传感器1
// 初始化Series
myChart.Series = new SeriesCollection
{
// 柱状图
new ColumnSeries
{
Title = "柱状数据",
Values = new ChartValues<double> { 20, 10, 12, 5, 9 }
},
// 标准1
new LineSeries
{
Title = "标准1",
Values = new ChartValues<double> { 5, 5, 5, 5, 5 },
DataLabels = true,
LabelPoint = value => value.Y.ToString("0.##") + " Hz",
StrokeThickness = 2,
Fill = System.Windows.Media.Brushes.Transparent
},
// 标准2
new LineSeries
{
Title = "标准2",
Values = new ChartValues<double> { 10, 10, 10, 10, 10 },
DataLabels = true,
LabelPoint = value => value.Y.ToString("0.##") + " Hz",
//Foreground = System.Windows.Media.Brushes.Blue,// 标签颜色
//FontSize = 14,// 字体大小
// StrokeThickness = 2, // 线条粗细
StrokeThickness = 2,
Stroke = System.Windows.Media.Brushes.Green,
Fill = System.Windows.Media.Brushes.Transparent
},
// 标准3
new LineSeries
{
Title = "标准3",
Values = new ChartValues<double> { 30, 30, 30, 30, 30 },
DataLabels = true,
LabelPoint = value => value.Y.ToString("0.##") + " Hz",
StrokeThickness = 2,
Stroke = System.Windows.Media.Brushes.Red,
Fill = System.Windows.Media.Brushes.Transparent
}
};
// 设置X轴标签
myChart.AxisX.Add(new Axis
{
Title = "",
Labels = new[] { "13:27 23", "13:27 45", "13:27 49", "13:27 50", "13:27 55" }
});
// 设置Y轴
myChart.AxisY.Add(new Axis
{
Title = ""
});
// 传感器2
// 初始化Series
myChart1.Series = new SeriesCollection
{
// 柱状图
new ColumnSeries
{
Title = "柱状数据",
Values = new ChartValues<double> { 20, 10, 12, 5, 9 }
},
// 标准1
new LineSeries
{
Title = "标准1",
Values = new ChartValues<double> { 5, 5, 5, 5, 5 },
StrokeThickness = 2,
Fill = System.Windows.Media.Brushes.Transparent
},
// 标准2
new LineSeries
{
Title = "标准2",
Values = new ChartValues<double> { 10, 10, 10, 10, 10 },
StrokeThickness = 2,
Stroke = System.Windows.Media.Brushes.Green,
Fill = System.Windows.Media.Brushes.Transparent
},
// 标准3
new LineSeries
{
Title = "标准3",
Values = new ChartValues<double> { 30, 30, 30, 30, 30 },
StrokeThickness = 2,
Stroke = System.Windows.Media.Brushes.Red,
Fill = System.Windows.Media.Brushes.Transparent
}
};
// 设置X轴标签
myChart1.AxisX.Add(new Axis
{
Title = "",
Labels = new[] { "13:27 23", "13:27 45", "13:27 49", "13:27 50", "13:27 55" }
});
// 设置Y轴
myChart1.AxisY.Add(new Axis
{
Title = ""
});
// 传感器3
// 初始化Series
myChart2.Series = new SeriesCollection
{
// 柱状图
new ColumnSeries
{
Title = "柱状数据",
Values = new ChartValues<double> { 20, 10, 12, 5, 9 }
},
// 标准1
new LineSeries
{
Title = "标准1",
Values = new ChartValues<double> { 5, 5, 5, 5, 5 },
StrokeThickness = 2,
Fill = System.Windows.Media.Brushes.Transparent
},
// 标准2
new LineSeries
{
Title = "标准2",
Values = new ChartValues<double> { 10, 10, 10, 10, 10 },
StrokeThickness = 2,
Stroke = System.Windows.Media.Brushes.Green,
Fill = System.Windows.Media.Brushes.Transparent
},
// 标准3
new LineSeries
{
Title = "标准3",
Values = new ChartValues<double> { 30, 30, 30, 30, 30 },
StrokeThickness = 2,
Stroke = System.Windows.Media.Brushes.Red,
Fill = System.Windows.Media.Brushes.Transparent
}
};
// 设置X轴标签
myChart2.AxisX.Add(new Axis
{
Title = "",
Labels = new[] { "13:27 23", "13:27 45", "13:27 49", "13:27 50", "13:27 55" }
});
// 设置Y轴
myChart2.AxisY.Add(new Axis
{
Title = ""
});
#endregion
}
private void Button_Click(object sender, RoutedEventArgs e)
{ {
SqlSugarScope scope = db.GetScope("LocalData"); ColumnData = new List<double> { 20, 10, 12, 5, 9 },
scope.guokeCheckToCreate<aaa>();//检查并创建表 Labels = new List<string>(labels),
even.TriggerEvent("GeneralEvent", this, new GeneralEventArgs("测试", 1)); LineConfigs = new List<LineConfig>
}
public class aaa : BaseTableModel
{ {
new LineConfig { Title = "标准1", Values = new List<double> { 5,5,5,5,5 }, Stroke = Brushes.Blue },
new LineConfig { Title = "标准2", Values = new List<double> { 10,10,10,10,10 }, Stroke = Brushes.Green },
new LineConfig { Title = "标准3", Values = new List<double> { 30,30,30,30,30 }, Stroke = Brushes.Red, Unit = "A" }
} }
/// <summary> };
/// 设置窗体标题的函数 InitChart.InitCartesianChart(myChart, config1);
/// </summary> InitChart.InitCartesianChart(myChart1, config1);
/// <param name="newTitle"></param> InitChart.InitCartesianChart(myChart2, config1);
public void SetWindowTitle(string newTitle)
{
this.Title = newTitle;
}
#region
// 在 MainWindow 内部
/// <summary>
/// 按钮点击触发文件页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnFilePageButtonClick(object sender, RoutedEventArgs e)
{
FilePage filePage = new FilePage();
NavigationWindow navWin = new NavigationWindow();
navWin.Width = 810;
navWin.Height = 600;
navWin.ResizeMode = ResizeMode.NoResize;
navWin.Content = filePage;
navWin.ShowsNavigationUI = false;
navWin.Title = "记录列表";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发配置页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnConfigPageButtonClick(object sender, RoutedEventArgs e)
{
ConfigPage configPage = new ConfigPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Content = configPage;
navWin.ShowsNavigationUI = false;
navWin.Width = 972;
navWin.Height = 648;
navWin.Title = "配置";
navWin.ResizeMode = ResizeMode.NoResize;
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发标准基准页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnStandardPageButtonClick(object sender, RoutedEventArgs e)
{
StandardPage standardPage = new StandardPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Width = 972;
navWin.Height = 648;
//navWin.ResizeMode = ResizeMode.NoResize;
navWin.Content = standardPage;
navWin.ShowsNavigationUI = false;
navWin.Title = "主标定";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发Gauge页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnGaugePageButtonClick(object sender, RoutedEventArgs e)
{
GaugePage gaugePage = new GaugePage();
NavigationWindow navWin = new NavigationWindow();
navWin.Content = gaugePage;
navWin.ShowsNavigationUI = false;
navWin.Width = 1080;
navWin.Height = 720;
navWin.Title = "Gauge R&&R";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发CgCgk页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnCgCgkPageButtonClick(object sender, RoutedEventArgs e)
{
CgCgkPage cgCgkPage = new CgCgkPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Content = cgCgkPage;
navWin.ShowsNavigationUI = false;
navWin.Title = "CgCgk";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发系统设置页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSysSetPageButtonClick(object sender, RoutedEventArgs e)
{
SysSetPage sysSetPage = new SysSetPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Width = 810;
navWin.Height = 600;
navWin.ResizeMode = ResizeMode.NoResize;
navWin.Content = sysSetPage;
navWin.ShowsNavigationUI = false;
navWin.Title = "系统设置";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
#endregion
#region
/// <summary>
/// 按钮点击触发关闭页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnCloseMainWindowButtonClick(object sender, RoutedEventArgs e)
{
this.Close();
}
/// <summary>
/// 测试按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDemoButtonClick(object sender, RoutedEventArgs e)
{
//LineBarChartDemo lineBarChartDemo = new LineBarChartDemo();
//lineBarChartDemo.Show();
}
/// <summary>
/// 等级选择下拉框变化事件处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LevelComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is ComboBox comboBox && comboBox.SelectedItem is ComboBoxItem selectedItem)
{
// 根据选择的Tag确定等级
SensorLevel selectedLevel = SensorLevel.Medium; // 默认值
switch (selectedItem.Tag?.ToString())
{
case "Low":
selectedLevel = SensorLevel.Low;
break;
case "Medium":
selectedLevel = SensorLevel.Medium;
break;
case "High":
selectedLevel = SensorLevel.High;
break;
}
// 更新所有传感器图表的等级
Sensor1.Level = selectedLevel;
Sensor2.Level = selectedLevel;
Sensor3.Level = selectedLevel;
}
}
#endregion
} }
private void Button_Click(object sender, RoutedEventArgs e)
{
SqlSugarScope scope = db.GetScope("LocalData");
scope.guokeCheckToCreate<aaa>();//检查并创建表
even.TriggerEvent("GeneralEvent", this, new GeneralEventArgs("测试", 1));
}
public class aaa : BaseTableModel
{
}
/// <summary>
/// 设置窗体标题的函数
/// </summary>
/// <param name="newTitle"></param>
public void SetWindowTitle(string newTitle)
{
this.Title = newTitle;
}
#region
// 在 MainWindow 内部
/// <summary>
/// 按钮点击触发文件页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnFilePageButtonClick(object sender, RoutedEventArgs e)
{
FilePage filePage = new FilePage();
NavigationWindow navWin = new NavigationWindow();
navWin.Width = 810;
navWin.Height = 600;
navWin.ResizeMode = ResizeMode.NoResize;
navWin.Content = filePage;
navWin.ShowsNavigationUI = false;
navWin.Title = "记录列表";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发配置页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnConfigPageButtonClick(object sender, RoutedEventArgs e)
{
ConfigPage configPage = new ConfigPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Content = configPage;
navWin.ShowsNavigationUI = false;
navWin.Width = 972;
navWin.Height = 648;
navWin.Title = "配置";
navWin.ResizeMode = ResizeMode.NoResize;
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发标准基准页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnStandardPageButtonClick(object sender, RoutedEventArgs e)
{
StandardPage standardPage = new StandardPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Width = 972;
navWin.Height = 648;
//navWin.ResizeMode = ResizeMode.NoResize;
navWin.Content = standardPage;
navWin.ShowsNavigationUI = false;
navWin.Title = "主标定";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发Gauge页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnGaugePageButtonClick(object sender, RoutedEventArgs e)
{
GaugePage gaugePage = new GaugePage();
NavigationWindow navWin = new NavigationWindow();
navWin.Content = gaugePage;
navWin.ShowsNavigationUI = false;
navWin.Width = 1080;
navWin.Height = 720;
navWin.Title = "Gauge R&&R";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发CgCgk页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnCgCgkPageButtonClick(object sender, RoutedEventArgs e)
{
CgCgkPage cgCgkPage = new CgCgkPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Content = cgCgkPage;
navWin.ShowsNavigationUI = false;
navWin.Title = "CgCgk";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
/// <summary>
/// 按钮点击触发系统设置页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSysSetPageButtonClick(object sender, RoutedEventArgs e)
{
SysSetPage sysSetPage = new SysSetPage();
NavigationWindow navWin = new NavigationWindow();
navWin.Width = 810;
navWin.Height = 600;
navWin.ResizeMode = ResizeMode.NoResize;
navWin.Content = sysSetPage;
navWin.ShowsNavigationUI = false;
navWin.Title = "系统设置";
// ✅ 新增:设定父窗口、样式与居中弹出
navWin.Owner = Application.Current.MainWindow; // 绑定主窗口
navWin.WindowStartupLocation = WindowStartupLocation.CenterOwner; // 居中弹出
navWin.WindowStyle = WindowStyle.ToolWindow;
// ✅ 改这里Show() 改为 ShowDialog() 实现模态窗口
navWin.ShowDialog();
}
#endregion
#region
/// <summary>
/// 按钮点击触发关闭页面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnCloseMainWindowButtonClick(object sender, RoutedEventArgs e)
{
this.Close();
}
/// <summary>
/// 测试按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDemoButtonClick(object sender, RoutedEventArgs e)
{
//LineBarChartDemo lineBarChartDemo = new LineBarChartDemo();
//lineBarChartDemo.Show();
}
/// <summary>
/// 等级选择下拉框变化事件处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LevelComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is ComboBox comboBox && comboBox.SelectedItem is ComboBoxItem selectedItem)
{
// 根据选择的Tag确定等级
SensorLevel selectedLevel = SensorLevel.Medium; // 默认值
switch (selectedItem.Tag?.ToString())
{
case "Low":
selectedLevel = SensorLevel.Low;
break;
case "Medium":
selectedLevel = SensorLevel.Medium;
break;
case "High":
selectedLevel = SensorLevel.High;
break;
}
// 更新所有传感器图表的等级
Sensor1.Level = selectedLevel;
Sensor2.Level = selectedLevel;
Sensor3.Level = selectedLevel;
}
}
#endregion
} }

58
Utils/InitChart.cs Normal file
View File

@ -0,0 +1,58 @@
using LiveCharts;
using LiveCharts.Wpf;
using System.Windows.Media;
using WpfApp.src.config;
namespace WpfApp.Utils;
public static class InitChart
{
public static void InitCartesianChart(CartesianChart chart, ChartConfig config)
{
chart.Series = new SeriesCollection();
// 柱状图
if (config.ColumnData != null && config.ColumnData.Count > 0)
{
chart.Series.Add(new ColumnSeries
{
Title = "柱状数据",
Values = new ChartValues<double>(config.ColumnData)
});
}
// 标准线条
foreach (var line in config.LineConfigs)
{
var lineSeries = new LineSeries
{
Title = line.Title,
Values = new ChartValues<double>(line.Values),
Stroke = line.Stroke ?? Brushes.Black,
StrokeThickness = 2,
Fill = Brushes.Transparent,
DataLabels = line.ShowLabel,
};
if (line.ShowLabel)
lineSeries.LabelPoint = value => $"{value.Y:0.##} {line.Unit}";
chart.Series.Add(lineSeries);
}
// X轴
chart.AxisX.Clear();
chart.AxisX.Add(new Axis
{
Title = config.XTitle ?? "",
Labels = config.Labels
});
// Y轴
chart.AxisY.Clear();
chart.AxisY.Add(new Axis
{
Title = config.YTitle ?? ""
});
}
}

View File

@ -1,402 +1,409 @@
using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
namespace WpfApp.src.components namespace WpfApp.src.components;
/// <summary>
/// 刻度线数据结构
/// </summary>
public class ScaleLine
{ {
/// <summary> public double Y1 { get; set; }
/// 刻度线数据结构 public double Y2 { get; set; }
/// </summary> public double X1 { get; set; }
public class ScaleLine 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; }
}
/// <summary>
/// SensorChart.xaml 的交互逻辑
/// </summary>
public partial class SensorChart : UserControl, INotifyPropertyChanged
{
public SensorChart()
{ {
public double Y1 { get; set; } InitializeComponent();
public double Y2 { get; set; } DataContext = this;
public double X1 { get; set; }
public double X2 { get; set; } // 设置默认值
public double StrokeThickness { get; set; } SensorName = "传感器";
public string Label { get; set; } HeaderBackground = new SolidColorBrush(Color.FromRgb(230, 243, 255)); // #E6F3FF
public double LabelX { get; set; } Value = 0;
public double LabelY { get; set; } RedLineValues = new List<double>();
public bool IsMainScale { get; set; } 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<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();
}
// 传感器等级
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<double> _redLinePositions = new List<double>();
public List<double> RedLinePositions
{
get { return _redLinePositions; }
private set
{
_redLinePositions = value;
OnPropertyChanged(nameof(RedLinePositions));
}
}
private List<ScaleLine> _scaleLines = new List<ScaleLine>();
public List<ScaleLine> 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
/// <summary>
/// 等级改变时的处理
/// </summary>
private void OnLevelChanged()
{
OnPropertyChanged(nameof(Level));
OnPropertyChanged(nameof(MinValue));
OnPropertyChanged(nameof(MaxValue));
GenerateScaleLines();
UpdateBarPosition();
UpdateRedLinePositions();
} }
/// <summary> /// <summary>
/// SensorChart.xaml 的交互逻辑 /// 生成刻度线
/// </summary> /// </summary>
public partial class SensorChart : UserControl, INotifyPropertyChanged private void GenerateScaleLines()
{ {
public SensorChart() var lines = new List<ScaleLine>();
double minVal = MinValue;
double maxVal = MaxValue;
// 根据等级确定刻度间隔
double mainInterval = (maxVal - minVal) / 8; // 8个主刻度间隔
double subInterval = mainInterval / 4; // 每个主刻度间隔4个小刻度
// 生成主刻度线
for (int i = 0; i <= 8; i++)
{ {
InitializeComponent(); double value = maxVal - i * mainInterval;
DataContext = this; double y = ValueToY(value);
// 设置默认值 lines.Add(new ScaleLine
SensorName = "传感器"; {
HeaderBackground = new SolidColorBrush(Color.FromRgb(230, 243, 255)); // #E6F3FF X1 = 40,
Value = 0; Y1 = y,
RedLineValues = new List<double>(); X2 = 130,
Level = SensorLevel.Medium; // 默认中等 Y2 = y,
StrokeThickness = 1,
Label = value.ToString("0"),
LabelX = 135,
LabelY = y - 5,
IsMainScale = true
});
// 生成初始刻度 // 生成小刻度线(除了最后一个主刻度)
GenerateScaleLines(); if (i < 8)
}
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();
}
// 传感器等级
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; for (int j = 1; j < 4; j++)
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));
}
}
private List<ScaleLine> _scaleLines = new List<ScaleLine>();
public List<ScaleLine> ScaleLines
{
get { return _scaleLines; }
private set
{
_scaleLines = value;
OnPropertyChanged(nameof(ScaleLines));
}
}
// 当前等级的最小值
public double MinValue
{
get
{
switch (Level)
{ {
case SensorLevel.Low: return -20; double subValue = value - j * subInterval;
case SensorLevel.Medium: return -40; double subY = ValueToY(subValue);
case SensorLevel.High: return -60;
default: return -40; lines.Add(new ScaleLine
}
}
}
// 当前等级的最大值
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
/// <summary>
/// 等级改变时的处理
/// </summary>
private void OnLevelChanged()
{
OnPropertyChanged(nameof(Level));
OnPropertyChanged(nameof(MinValue));
OnPropertyChanged(nameof(MaxValue));
GenerateScaleLines();
UpdateBarPosition();
UpdateRedLinePositions();
}
/// <summary>
/// 生成刻度线
/// </summary>
private void GenerateScaleLines()
{
var lines = new List<ScaleLine>();
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; X1 = 40,
double subY = ValueToY(subValue); Y1 = subY,
X2 = 125,
lines.Add(new ScaleLine Y2 = subY,
{ StrokeThickness = 0.5,
X1 = 40, Label = "",
Y1 = subY, LabelX = 0,
X2 = 125, LabelY = 0,
Y2 = subY, IsMainScale = false
StrokeThickness = 0.5, });
Label = "",
LabelX = 0,
LabelY = 0,
IsMainScale = false
});
}
} }
} }
ScaleLines = lines;
} }
/// <summary> ScaleLines = lines;
/// 将数值转换为Y坐标位置
/// 根据当前等级动态计算刻度范围
/// </summary>
/// <param name="value">数值</param>
/// <returns>Y坐标</returns>
private double ValueToY(double value)
{
double minVal = MinValue;
double maxVal = MaxValue;
// 限制数值范围
value = Math.Max(minVal, Math.Min(maxVal, value));
// 线性映射maxVal对应Y=20minVal对应Y=420
double range = maxVal - minVal;
return 220 - ((value - minVal) / range - 0.5) * 400;
}
/// <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>
/// <param name="level">传感器等级</param>
public void SetSensorData(string name, double value, List<double> redLines = null, Color? headerColor = null, SensorLevel? level = null)
{
SensorName = name;
Value = value;
if (redLines != null)
{
RedLineValues = new List<double>(redLines);
}
if (headerColor.HasValue)
{
HeaderBackground = new SolidColorBrush(headerColor.Value);
}
if (level.HasValue)
{
Level = level.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
} }
/// <summary>
/// 将数值转换为Y坐标位置
/// 根据当前等级动态计算刻度范围
/// </summary>
/// <param name="value">数值</param>
/// <returns>Y坐标</returns>
private double ValueToY(double value)
{
double minVal = MinValue;
double maxVal = MaxValue;
// 限制数值范围
value = Math.Max(minVal, Math.Min(maxVal, value));
// 线性映射maxVal对应Y=20minVal对应Y=420
double range = maxVal - minVal;
return 220 - ((value - minVal) / range - 0.5) * 400;
}
/// <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>
/// <param name="level">传感器等级</param>
public void SetSensorData(string name, double value, List<double> redLines = null, Color? headerColor = null, SensorLevel? level = null)
{
SensorName = name;
Value = value;
if (redLines != null)
{
RedLineValues = new List<double>(redLines);
}
if (headerColor.HasValue)
{
HeaderBackground = new SolidColorBrush(headerColor.Value);
}
if (level.HasValue)
{
Level = level.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
}
/// <summary>
/// 传感器等级枚举
/// </summary>
public enum SensorLevel
{
Low, // 低等:-20到20
Medium, // 中等:-40到40
High // 高等:-60到60
} }

View File

@ -1,12 +0,0 @@
namespace WpfApp.src.components
{
/// <summary>
/// 传感器等级枚举
/// </summary>
public enum SensorLevel
{
Low, // 低等:-20到20
Medium, // 中等:-40到40
High // 高等:-60到60
}
}

36
src/config/ChartConfig.cs Normal file
View File

@ -0,0 +1,36 @@
using System.Windows.Media;
namespace WpfApp.src.config;
public class ChartConfig
{
public List<double> ColumnData { get; set; } = new();
public List<LineConfig> LineConfigs { get; set; } = new();
public List<string> Labels { get; set; } = new();
public string XTitle { get; set; }
public string YTitle { get; set; }
}
public class LineConfig
{
/// <summary>
/// 曲线标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 曲线的值
/// </summary>
public List<double> Values { get; set; }
/// <summary>
/// 曲线颜色
/// </summary>
public Brush Stroke { get; set; } = Brushes.Black;
/// <summary>
/// 是否显示数据点上的标签
/// </summary>
public bool ShowLabel { get; set; } = true;
/// <summary>
/// 单位
/// </summary>
public string Unit { get; set; } = "Hz";
}