为 WPF C# 上位机量身定制的完整内容
·
以下是为 WPF C# 上位机量身定制的完整内容,已按您的要求整理:
1. 完整 Demo 工程结构(WPF版)
IndustrialMonitor.WPF/
├── IndustrialMonitor/ # 主启动项目
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── MainWindow.xaml # 主窗口 (Shell)
│ ├── MainWindow.xaml.cs
│ │
│ ├── Core/ # 核心领域模型
│ │ ├── Models/
│ │ ├── Events/ # Prism EventAggregator 事件
│ │ └── Interfaces/
│ │
│ ├── Services/ # 服务层
│ │ ├── Device/
│ │ ├── LinkageService.cs # 联动引擎
│ │ ├── AlarmService.cs # 报警中心
│ │ ├── LoggingService.cs
│ │ ├── DataAcquisitionService.cs
│ │ └── EmailService.cs
│ │
│ ├── Views/ # WPF 视图
│ │ ├── DashboardView.xaml # 主监控仪表盘
│ │ ├── LinkageRuleEditorView.xaml # 联动规则配置界面
│ │ ├── AlarmCenterView.xaml # 报警中心
│ │ ├── HistoryView.xaml
│ │ └── DeviceListView.xaml
│ │
│ ├── ViewModels/ # MVVM
│ │ ├── MainViewModel.cs
│ │ ├── DashboardViewModel.cs
│ │ ├── LinkageRuleViewModel.cs
│ │ └── AlarmCenterViewModel.cs
│ │
│ ├── Controls/ # 自定义控件(Gauge、TrendChart等)
│ ├── Helpers/
│ ├── Assets/ # 图片、图标
│ └── Properties/
│
├── IndustrialMonitor.Core/ # 共享类库(可选)
├── IndustrialMonitor.Tests/
└── packages/
推荐 NuGet 包:
Prism.Wpf(模块化 + EventAggregator)CommunityToolkit.MvvmSerilog+Serilog.Sinks.SQLite+Serilog.Sinks.MSSqlServerOxyPlot.WpfMailKit(邮件推送)
2. 联动规则可视化配置界面(WPF版)
LinkageRuleEditorView.xaml
<UserControl x:Class="IndustrialMonitor.Views.LinkageRuleEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 工具栏 -->
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,8">
<Button Content="新增规则" Width="100" Margin="5" Command="{Binding AddRuleCommand}"/>
<Button Content="保存所有规则" Width="120" Margin="5" Command="{Binding SaveAllCommand}"/>
<Button Content="删除选中" Width="100" Margin="5" Command="{Binding DeleteRuleCommand}"/>
</StackPanel>
<!-- 规则列表 -->
<DataGrid Grid.Row="1" ItemsSource="{Binding Rules}"
SelectedItem="{Binding SelectedRule}"
AutoGenerateColumns="False" IsReadOnly="False">
<DataGrid.Columns>
<DataGridTextColumn Header="规则名称" Binding="{Binding RuleName}" Width="180"/>
<DataGridTextColumn Header="源设备" Binding="{Binding SourceDeviceName}" Width="120"/>
<DataGridTextColumn Header="条件描述" Binding="{Binding ConditionDescription}" Width="250"/>
<DataGridTextColumn Header="动作数量" Binding="{Binding Actions.Count}" Width="80"/>
<DataGridCheckBoxColumn Header="启用" Binding="{Binding IsEnabled}" Width="60"/>
</DataGrid.Columns>
</DataGrid>
<!-- 选中规则详细编辑 -->
<GroupBox Grid.Row="2" Header="规则详细编辑" Margin="0,10,0,0"
DataContext="{Binding SelectedRule}">
<StackPanel Margin="8">
<TextBlock Text="规则名称"/>
<TextBox Text="{Binding RuleName, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="条件表达式" Margin="0,8,0,4"/>
<TextBox Text="{Binding ConditionExpression}" Height="80" AcceptsReturn="True"
VerticalScrollBarVisibility="Auto"/>
<Button Content="添加联动动作" Margin="0,8" Command="{Binding AddActionCommand}"/>
</StackPanel>
</GroupBox>
</Grid>
</UserControl>
ViewModel 关键代码(LinkageRuleViewModel.cs)
public partial class LinkageRuleViewModel : ObservableObject
{
[ObservableProperty] private ObservableCollection<LinkageRule> rules = new();
[ObservableProperty] private LinkageRule? selectedRule;
[RelayCommand]
private void AddRule()
{
var newRule = new LinkageRule
{
RuleName = $"联动规则 {rules.Count + 1}",
IsEnabled = true
};
rules.Add(newRule);
SelectedRule = newRule;
}
[RelayCommand]
private async Task SaveAll()
{
await _linkageService.SaveRulesAsync(rules.ToList());
Log.Information("联动规则保存成功,共 {Count} 条", rules.Count);
}
}
3. Serilog + SQLite 完整建表与查询代码
Serilog 配置(App.xaml.cs)
private void ConfigureLogging()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.WriteTo.SQLite(
path: "Data/IndustrialMonitor.db",
tableName: "SystemLogs",
storeTimestampInUtc: true)
.WriteTo.File("Logs/log_.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
}
SQLite 表结构(自动创建)
-- 系统日志表
CREATE TABLE IF NOT EXISTS SystemLogs (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Timestamp TEXT NOT NULL,
Level TEXT NOT NULL,
Message TEXT,
DeviceId TEXT,
RuleName TEXT,
Parameter TEXT,
Value REAL,
Exception TEXT,
Properties TEXT
);
-- 报警记录表
CREATE TABLE IF NOT EXISTS AlarmLogs (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
AlarmTime TEXT NOT NULL,
DeviceId TEXT,
AlarmType TEXT,
Description TEXT,
Severity INTEGER,
Value REAL,
Threshold REAL,
IsConfirmed INTEGER DEFAULT 0,
ConfirmTime TEXT,
ConfirmedBy TEXT
);
查询示例
public async Task<List<AlarmLog>> GetAlarmsAsync(DateTime start, DateTime end, int severity = 0)
{
using var conn = new SQLiteConnection("Data Source=Data/IndustrialMonitor.db");
string sql = "SELECT * FROM AlarmLogs WHERE AlarmTime BETWEEN @start AND @end";
if (severity > 0)
sql += " AND Severity >= @severity";
sql += " ORDER BY AlarmTime DESC LIMIT 500";
return await conn.QueryAsync<AlarmLog>(sql, new { start, end, severity });
}
4. 报警中心与邮件/短信推送实现
AlarmService.cs
public class AlarmService
{
private readonly Serilog.ILogger _logger;
private readonly IEmailService _emailService;
public event EventHandler<AlarmEventArgs>? OnNewAlarm;
public void RaiseAlarm(AlarmEventArgs alarm)
{
_logger.Warning("【{Severity}报警】{Device} - {Desc} | 当前值:{Value}",
alarm.Severity, alarm.DeviceId, alarm.Description, alarm.Value);
OnNewAlarm?.Invoke(this, alarm);
// 高危报警邮件推送
if (alarm.Severity >= AlarmSeverity.High)
_emailService.SendAlarmAsync(alarm);
SaveToDatabase(alarm);
}
private void SaveToDatabase(AlarmEventArgs alarm)
{
// 使用 Dapper 或 EF Core 写入 AlarmLogs 表
}
}
邮件推送(MailKit)
public async Task SendAlarmAsync(AlarmEventArgs alarm)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("工业监控系统", "monitor@yourcompany.com"));
message.To.Add(new MailboxAddress("值班工程师", "engineer@yourcompany.com"));
message.Subject = $"【紧急】{alarm.DeviceId} {alarm.Description}";
message.Body = new TextPart("html")
{
Text = $"""
<h2 style="color:red">报警信息</h2>
<p><strong>时间:</strong>{DateTime.Now:yyyy-MM-dd HH:mm:ss}</p>
<p><strong>设备:</strong>{alarm.DeviceId}</p>
<p><strong>描述:</strong>{alarm.Description}</p>
<p><strong>当前值:</strong>{alarm.Value}</p>
"""
};
using var client = new SmtpClient();
await client.ConnectAsync("smtp.exmail.qq.com", 465, true);
await client.AuthenticateAsync("xxx@exmail.qq.com", "password");
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
短信推送:可接入阿里云/腾讯云短信服务,封装类似方法即可。
需要我继续补充以下任意部分?
- DashboardView + OxyPlot 实时曲线 完整代码
- Prism EventAggregator 事件定义与使用示例
- MainWindow.xaml 整体布局
- ValueTask 高频采集服务 完整实现
请告诉我优先需要哪一块,我会立即输出!
更多推荐
所有评论(0)