This commit is contained in:
1
App.xaml
1
App.xaml
@@ -8,5 +8,6 @@
|
||||
<converters:BoolToStringConverter x:Key="BoolToStringConverter"/>
|
||||
<converters:InverseBoolConverter x:Key="InverseBoolConverter"/>
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
<converters:BoolToYesNoConverter x:Key="BoolToYesNoConverter"/>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -11,4 +11,6 @@ namespace AciTester
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
18
Converters/BoolToYesNoConverter.cs
Normal file
18
Converters/BoolToYesNoConverter.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace AciTester.Converters
|
||||
{
|
||||
public class BoolToYesNoConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> (value is bool b && b) ? "正在除霜" : "";
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -21,5 +21,8 @@ namespace AciTester.Models
|
||||
|
||||
[ObservableProperty]
|
||||
private float flowHighLimit = 32.0f; // D1332 高限
|
||||
|
||||
[ObservableProperty]
|
||||
private float temperatureProtect = 40.0f; // D1084
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,20 @@ namespace AciTester.Models
|
||||
public ushort ImpactorPressureCalibCoil { get; set; } = 1303; // M1303
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public ushort AcLowPressureAlarmCoil { get; set; } = 1001; // M1001
|
||||
public ushort AcHighPressureAlarmCoil { get; set; } = 1002; // M1002
|
||||
public ushort AcStartupCountdownReg { get; set; } = 50; // D50 (双整数)
|
||||
public ushort DefrostTempSetReg { get; set; } = 302; // D302 (浮点)
|
||||
public ushort DefrostTimeSetReg { get; set; } = 310; // D310 (双整数)
|
||||
public ushort DefrostMinuteReg { get; set; } = 42; // D42 (双整数)
|
||||
public ushort DefrostSecondReg { get; set; } = 40; // D40 (双整数)
|
||||
public ushort TempProtectReg { get; set; } = 1084; // D1084 (浮点)
|
||||
public ushort ConstantTempStartCoil { get; set; } = 4; // M4
|
||||
public ushort DefrostStartCoil { get; set; } = 19; // M19
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -97,5 +111,8 @@ namespace AciTester.Models
|
||||
void Dispose();
|
||||
|
||||
bool IsConnected { get; } // 新增
|
||||
|
||||
Task<int> ReadInt32Async(ushort startAddress);
|
||||
Task WriteInt32Async(ushort startAddress, int value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,5 +21,45 @@ namespace AciTester.Models
|
||||
|
||||
[ObservableProperty]
|
||||
private float differentialPressure; // 压差 = impactorPressure - pumpPressure
|
||||
|
||||
|
||||
|
||||
// 新增
|
||||
[ObservableProperty]
|
||||
private int acStartupCountdown; // D50
|
||||
|
||||
private float _defrostTempSet;
|
||||
public float DefrostTempSet
|
||||
{
|
||||
get => _defrostTempSet;
|
||||
set => SetProperty(ref _defrostTempSet, value);
|
||||
}
|
||||
|
||||
private int _defrostTimeSet;
|
||||
public int DefrostTimeSet
|
||||
{
|
||||
get => _defrostTimeSet;
|
||||
set => SetProperty(ref _defrostTimeSet, value);
|
||||
} // D302
|
||||
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
private int defrostMinute; // D42
|
||||
|
||||
[ObservableProperty]
|
||||
private int defrostSecond; // D40
|
||||
|
||||
[ObservableProperty]
|
||||
private bool constantTempStart; // M4
|
||||
|
||||
[ObservableProperty]
|
||||
private bool defrostStart; // M19
|
||||
|
||||
[ObservableProperty]
|
||||
private bool acLowPressureAlarm; // M1001
|
||||
|
||||
[ObservableProperty]
|
||||
private bool acHighPressureAlarm; // M1002
|
||||
}
|
||||
}
|
||||
@@ -188,6 +188,24 @@ namespace AciTester.Services
|
||||
_tcpClient?.Close();
|
||||
_tcpClient?.Dispose();
|
||||
}
|
||||
|
||||
|
||||
public async Task<int> ReadInt32Async(ushort startAddress)
|
||||
{
|
||||
await EnsureConnectedAsync();
|
||||
var regs = await ReadHoldingRegistersAsync(startAddress, 2);
|
||||
return (regs[0] << 16) | regs[1];
|
||||
}
|
||||
|
||||
public async Task WriteInt32Async(ushort startAddress, int value)
|
||||
{
|
||||
await EnsureConnectedAsync();
|
||||
var bytes = BitConverter.GetBytes(value);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
|
||||
ushort high = (ushort)((bytes[0] << 8) | bytes[1]);
|
||||
ushort low = (ushort)((bytes[2] << 8) | bytes[3]);
|
||||
await _master.WriteMultipleRegistersAsync(_config.SlaveId, startAddress, new ushort[] { high, low });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using AciTester.Models;
|
||||
using AciTester.Services;
|
||||
using AciTester.Views;
|
||||
|
||||
namespace AciTester.ViewModels
|
||||
{
|
||||
@@ -17,6 +16,8 @@ namespace AciTester.ViewModels
|
||||
private readonly IReportService _reportService;
|
||||
public readonly PlcConfiguration _config;
|
||||
private CancellationTokenSource _testCts;
|
||||
private bool _alarmShownLow = false;
|
||||
private bool _alarmShownHigh = false;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isConnected;
|
||||
@@ -34,7 +35,7 @@ namespace AciTester.ViewModels
|
||||
private bool isTesting;
|
||||
|
||||
[ObservableProperty]
|
||||
private int sampleTimeSeconds = 60; // 默认采样60秒
|
||||
private int sampleTimeSeconds = 60;
|
||||
|
||||
[ObservableProperty]
|
||||
private int remainingSeconds;
|
||||
@@ -45,21 +46,21 @@ namespace AciTester.ViewModels
|
||||
[ObservableProperty]
|
||||
private TestResult currentResult;
|
||||
|
||||
// 在 MainViewModel 中添加
|
||||
[ObservableProperty]
|
||||
private RealTimeData realTime;
|
||||
|
||||
[ObservableProperty]
|
||||
private CalibrationConfig calibration;
|
||||
|
||||
private Timer _dataTimer;
|
||||
[ObservableProperty]
|
||||
private bool constantTempStartEnabled = true; // 是否允许恒温启动(除霜时为false)
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
_config = new PlcConfiguration();
|
||||
_plcService = new ModbusTcpPlcService(_config);
|
||||
_reportService = new ExcelReportService();
|
||||
|
||||
// 初始化ACI 8级 + 滤膜
|
||||
Stages = new ObservableCollection<StageData>
|
||||
{
|
||||
new StageData { StageName = "Stage 0", CutoffDiameter = 9.0 },
|
||||
@@ -79,17 +80,27 @@ namespace AciTester.ViewModels
|
||||
CalculateCommand = new RelayCommand(CalculateResult);
|
||||
ExportReportCommand = new AsyncRelayCommand(ExportReportAsync);
|
||||
|
||||
// 在构造函数中初始化
|
||||
// 写入命令
|
||||
WriteConstantTempStartCommand = new AsyncRelayCommand<bool>(WriteConstantTempStartAsync);
|
||||
WriteDefrostStartCommand = new AsyncRelayCommand<bool>(WriteDefrostStartAsync);
|
||||
WriteDefrostTempSetCommand = new AsyncRelayCommand<float>(WriteDefrostTempSetAsync);
|
||||
WriteDefrostTimeSetCommand = new AsyncRelayCommand<int>(WriteDefrostTimeSetAsync);
|
||||
|
||||
RealTime = new RealTimeData();
|
||||
Calibration = new CalibrationConfig();
|
||||
|
||||
|
||||
//this.Loaded += (s, e) =>
|
||||
//{
|
||||
// var keyGesture = new KeyGesture(Key.P, ModifierKeys.Control);
|
||||
// var inputBinding = new InputBinding(new RelayCommand(OpenConfigWindow), keyGesture);
|
||||
// this.InputBindings.Add(inputBinding);
|
||||
//};
|
||||
// 监听属性变化,当除霜启动时更新恒温启动使能
|
||||
RealTime.PropertyChanged += async (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(RealTime.DefrostTempSet))
|
||||
{
|
||||
await WriteDefrostTempSetAsync(RealTime.DefrostTempSet);
|
||||
}
|
||||
else if (e.PropertyName == nameof(RealTime.DefrostTimeSet))
|
||||
{
|
||||
await WriteDefrostTimeSetAsync(RealTime.DefrostTimeSet);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IAsyncRelayCommand ConnectCommand { get; }
|
||||
@@ -97,6 +108,10 @@ namespace AciTester.ViewModels
|
||||
public IAsyncRelayCommand StartTestCommand { get; }
|
||||
public IRelayCommand CalculateCommand { get; }
|
||||
public IAsyncRelayCommand ExportReportCommand { get; }
|
||||
public IAsyncRelayCommand<bool> WriteConstantTempStartCommand { get; }
|
||||
public IAsyncRelayCommand<bool> WriteDefrostStartCommand { get; }
|
||||
public IAsyncRelayCommand<float> WriteDefrostTempSetCommand { get; }
|
||||
public IAsyncRelayCommand<int> WriteDefrostTimeSetCommand { get; }
|
||||
|
||||
private async Task ConnectAsync()
|
||||
{
|
||||
@@ -106,7 +121,9 @@ namespace AciTester.ViewModels
|
||||
IsConnected = true;
|
||||
ConnectionStatus = "已连接";
|
||||
_ = Task.Run(ReadFlowLoop);
|
||||
_ = Task.Run(ReadRealTimeLoop); // 新增
|
||||
_ = Task.Run(ReadRealTimeLoop);
|
||||
_ = Task.Run(ReadAlarmLoop); // 报警循环
|
||||
_ = Task.Run(ReadDefrostStatusLoop); // 除霜相关状态
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -137,6 +154,162 @@ namespace AciTester.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReadRealTimeLoop()
|
||||
{
|
||||
while (IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
var rawFlow = await _plcService.ReadFloatAsync(_config.FlowRegister);
|
||||
var calibrated = rawFlow * Calibration.FlowCalibration;
|
||||
var temp = await _plcService.ReadFloatAsync(_config.TemperatureReg);
|
||||
var calibratedTemp = temp * Calibration.TemperatureCalibration;
|
||||
var pumpPres = await _plcService.ReadFloatAsync(_config.PumpPressureReg);
|
||||
var calibratedPump = pumpPres * Calibration.PumpPressureCalibration;
|
||||
var impPres = await _plcService.ReadFloatAsync(_config.ImpactorPressureReg);
|
||||
var calibratedImp = impPres * Calibration.ImpactorPressureCalibration;
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
RealTime.RawFlow = rawFlow;
|
||||
RealTime.CalibratedFlow = calibrated;
|
||||
RealTime.Temperature = calibratedTemp;
|
||||
RealTime.PumpPressure = calibratedPump;
|
||||
RealTime.ImpactorPressure = calibratedImp;
|
||||
RealTime.DifferentialPressure = calibratedImp - calibratedPump;
|
||||
});
|
||||
|
||||
if (calibrated < Calibration.FlowLowLimit || calibrated > Calibration.FlowHighLimit)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
MessageBox.Show($"流量异常: {calibrated:F2} L/min", "警告", MessageBoxButton.OK, MessageBoxImage.Warning));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReadAlarmLoop()
|
||||
{
|
||||
while (IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
var lowAlarm = await _plcService.ReadCoilAsync(_config.AcLowPressureAlarmCoil);
|
||||
var highAlarm = await _plcService.ReadCoilAsync(_config.AcHighPressureAlarmCoil);
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
RealTime.AcLowPressureAlarm = lowAlarm;
|
||||
RealTime.AcHighPressureAlarm = highAlarm;
|
||||
});
|
||||
|
||||
if (lowAlarm && !_alarmShownLow)
|
||||
{
|
||||
_alarmShownLow = true;
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var result = MessageBox.Show("空调低压报警,请检查空调情况", "报警", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
if (result == MessageBoxResult.OK)
|
||||
{
|
||||
_ = _plcService.WriteCoilAsync(_config.AcLowPressureAlarmCoil, false);
|
||||
_alarmShownLow = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (highAlarm && !_alarmShownHigh)
|
||||
{
|
||||
_alarmShownHigh = true;
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var result = MessageBox.Show("空调高压报警,请检查空调情况", "报警", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
if (result == MessageBoxResult.OK)
|
||||
{
|
||||
_ = _plcService.WriteCoilAsync(_config.AcHighPressureAlarmCoil, false);
|
||||
_alarmShownHigh = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
await Task.Delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReadDefrostStatusLoop()
|
||||
{
|
||||
while (IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 读取 D50 空调启动倒计时
|
||||
var countdown = await _plcService.ReadInt32Async(_config.AcStartupCountdownReg);
|
||||
// 读取 D302 除霜温度设置
|
||||
var defrostTemp = await _plcService.ReadFloatAsync(_config.DefrostTempSetReg);
|
||||
// 读取 D310 除霜时间设置
|
||||
var defrostTime = await _plcService.ReadInt32Async(_config.DefrostTimeSetReg);
|
||||
// 读取 D42 D40 除霜计时
|
||||
var min = await _plcService.ReadInt32Async(_config.DefrostMinuteReg);
|
||||
var sec = await _plcService.ReadInt32Async(_config.DefrostSecondReg);
|
||||
// 读取 M4 M19
|
||||
var constTemp = await _plcService.ReadCoilAsync(_config.ConstantTempStartCoil);
|
||||
var defrostStart = await _plcService.ReadCoilAsync(_config.DefrostStartCoil);
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
RealTime.AcStartupCountdown = countdown;
|
||||
RealTime.DefrostTempSet = defrostTemp;
|
||||
RealTime.DefrostTimeSet = defrostTime;
|
||||
RealTime.DefrostMinute = min;
|
||||
RealTime.DefrostSecond = sec;
|
||||
RealTime.ConstantTempStart = constTemp;
|
||||
RealTime.DefrostStart = defrostStart;
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WriteConstantTempStartAsync(bool value)
|
||||
{
|
||||
if (!IsConnected) return;
|
||||
if (RealTime.DefrostStart)
|
||||
{
|
||||
MessageBox.Show("设备正在除霜,不能进行恒温操作", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
await _plcService.WriteCoilAsync(_config.ConstantTempStartCoil, value);
|
||||
}
|
||||
|
||||
private async Task WriteDefrostStartAsync(bool value)
|
||||
{
|
||||
if (!IsConnected) return;
|
||||
await _plcService.WriteCoilAsync(_config.DefrostStartCoil, value);
|
||||
if (value)
|
||||
{
|
||||
// 立即更新界面使能
|
||||
ConstantTempStartEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstantTempStartEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WriteDefrostTempSetAsync(float value)
|
||||
{
|
||||
if (!IsConnected) return;
|
||||
await _plcService.WriteMultipleRegistersAsync(_config.DefrostTempSetReg, value);
|
||||
}
|
||||
|
||||
private async Task WriteDefrostTimeSetAsync(int value)
|
||||
{
|
||||
if (!IsConnected) return;
|
||||
await _plcService.WriteInt32Async(_config.DefrostTimeSetReg, value);
|
||||
}
|
||||
|
||||
private async Task StartTestAsync()
|
||||
{
|
||||
if (!IsConnected)
|
||||
@@ -152,11 +325,9 @@ namespace AciTester.ViewModels
|
||||
|
||||
try
|
||||
{
|
||||
// 启动真空泵
|
||||
await _plcService.WriteCoilAsync(_config.PumpCoil, true);
|
||||
IsPumpRunning = true;
|
||||
|
||||
// 倒计时
|
||||
RemainingSeconds = SampleTimeSeconds;
|
||||
for (int i = 0; i < SampleTimeSeconds; i++)
|
||||
{
|
||||
@@ -165,7 +336,6 @@ namespace AciTester.ViewModels
|
||||
RemainingSeconds--;
|
||||
}
|
||||
|
||||
// 停止泵
|
||||
await _plcService.WriteCoilAsync(_config.PumpCoil, false);
|
||||
IsPumpRunning = false;
|
||||
|
||||
@@ -175,7 +345,6 @@ namespace AciTester.ViewModels
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"测试异常: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
// 尝试停止泵
|
||||
try { await _plcService.WriteCoilAsync(_config.PumpCoil, false); } catch { }
|
||||
IsPumpRunning = false;
|
||||
}
|
||||
@@ -198,16 +367,15 @@ namespace AciTester.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
// 微细粒子剂量:截止直径 ≤ 5μm 的级 + 滤膜
|
||||
double fineMass = 0;
|
||||
foreach (var stage in Stages)
|
||||
{
|
||||
if (stage.CutoffDiameter <= 5.0 && stage.CutoffDiameter > 0)
|
||||
fineMass += stage.NetWeight;
|
||||
}
|
||||
fineMass += Stages[8].NetWeight; // 滤膜
|
||||
fineMass += Stages[8].NetWeight;
|
||||
|
||||
double fpd = fineMass * 1000; // mg
|
||||
double fpd = fineMass * 1000;
|
||||
double fpf = (fineMass / totalMass) * 100;
|
||||
|
||||
CurrentResult = new TestResult
|
||||
@@ -218,8 +386,8 @@ namespace AciTester.ViewModels
|
||||
FineParticleFraction = fpf,
|
||||
Stages = Stages.ToList(),
|
||||
FlowRate = CurrentFlow,
|
||||
Temperature = RealTime.Temperature, // 新增
|
||||
DifferentialPressure = RealTime.DifferentialPressure // 新增
|
||||
Temperature = RealTime.Temperature,
|
||||
DifferentialPressure = RealTime.DifferentialPressure
|
||||
};
|
||||
|
||||
MessageBox.Show($"计算完成\n总质量: {totalMass:F4} g\n微细粒子剂量: {fpd:F2} mg\n微细粒子分数: {fpf:F2}%",
|
||||
@@ -245,61 +413,5 @@ namespace AciTester.ViewModels
|
||||
MessageBox.Show("报告已保存", "完成", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 启动定时读取(连接成功后)
|
||||
private async Task ReadRealTimeLoop()
|
||||
{
|
||||
while (IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 读取原始流量
|
||||
var rawFlow = await _plcService.ReadFloatAsync(_config.FlowRegister);
|
||||
// 校准流量 = 原始流量 * 流量系数
|
||||
var calibrated = rawFlow * Calibration.FlowCalibration;
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
RealTime.RawFlow = rawFlow;
|
||||
RealTime.CalibratedFlow = calibrated;
|
||||
});
|
||||
|
||||
// 温度
|
||||
var temp = await _plcService.ReadFloatAsync(_config.TemperatureReg);
|
||||
var calibratedTemp = temp * Calibration.TemperatureCalibration;
|
||||
Application.Current.Dispatcher.Invoke(() => RealTime.Temperature = calibratedTemp);
|
||||
|
||||
// 泵端压力
|
||||
var pumpPres = await _plcService.ReadFloatAsync(_config.PumpPressureReg);
|
||||
var calibratedPump = pumpPres * Calibration.PumpPressureCalibration;
|
||||
Application.Current.Dispatcher.Invoke(() => RealTime.PumpPressure = calibratedPump);
|
||||
|
||||
// 撞击器端压力
|
||||
var impPres = await _plcService.ReadFloatAsync(_config.ImpactorPressureReg);
|
||||
var calibratedImp = impPres * Calibration.ImpactorPressureCalibration;
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
RealTime.ImpactorPressure = calibratedImp;
|
||||
RealTime.DifferentialPressure = calibratedImp - calibratedPump;
|
||||
});
|
||||
|
||||
// 流量报警检查
|
||||
if (calibrated < Calibration.FlowLowLimit || calibrated > Calibration.FlowHighLimit)
|
||||
{
|
||||
// 可触发界面警告
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
MessageBox.Show($"流量异常: {calibrated:F2} L/min", "警告", MessageBoxButton.OK, MessageBoxImage.Warning));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<GroupBox Header="流量校准" Grid.Row="0">
|
||||
@@ -41,7 +42,14 @@
|
||||
<TextBox Text="{Binding Calibration.ImpactorPressureCalibration}" Width="100"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10">
|
||||
|
||||
<GroupBox Header="温度保护" Grid.Row="4" Margin="0,10">
|
||||
<StackPanel Orientation="Horizontal" Margin="5">
|
||||
<TextBlock Text="温度保护值(℃):" Width="120"/>
|
||||
<TextBox Text="{Binding Calibration.TemperatureProtect}" Width="100"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10">
|
||||
<Button Command="{Binding LoadConfigCommand}" Content="读取" Width="80" Margin="5"/>
|
||||
<Button Command="{Binding SaveConfigCommand}" Content="保存" Width="80" Margin="5"/>
|
||||
<Button Click="CloseWindow" Content="关闭" Width="80" Margin="5"/>
|
||||
|
||||
@@ -4,12 +4,85 @@
|
||||
xmlns:local="clr-namespace:AciTester.ViewModels"
|
||||
Title="ACI测试系统 - 中国药典2025装置3"
|
||||
Height="768" Width="1024"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Background="#F0F2F5">
|
||||
<Window.DataContext>
|
||||
<local:MainViewModel/>
|
||||
</Window.DataContext>
|
||||
<Grid Margin="10">
|
||||
|
||||
<Window.Resources>
|
||||
<!-- 按钮样式 -->
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Height" Value="40"/>
|
||||
<Setter Property="Margin" Value="5"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Background" Value="#2C7DA0"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="BorderBrush" Value="#1F5E7A"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Background" Value="#CCCCCC"/>
|
||||
<Setter Property="Foreground" Value="#666666"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#1F5E7A"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<!-- 文本框样式 -->
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="Height" Value="35"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="BorderBrush" Value="#CCCCCC"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Padding" Value="5"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
|
||||
<!-- 切换按钮样式 -->
|
||||
<Style TargetType="ToggleButton">
|
||||
<Setter Property="Height" Value="40"/>
|
||||
<Setter Property="Width" Value="80"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Background" Value="#E74C3C"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Background" Value="#27AE60"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<!-- DataGrid 样式 -->
|
||||
<Style TargetType="DataGrid">
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="RowHeight" Value="30"/>
|
||||
<Setter Property="HeadersVisibility" Value="Column"/>
|
||||
<Setter Property="GridLinesVisibility" Value="Horizontal"/>
|
||||
<Setter Property="AlternatingRowBackground" Value="#F9F9F9"/>
|
||||
</Style>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="Height" Value="35"/>
|
||||
<Setter Property="Background" Value="#E9F0F5"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style TargetType="DataGridCell">
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid Margin="15">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
@@ -17,127 +90,192 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 状态栏 (Row 0) -->
|
||||
<StatusBar Grid.Row="0">
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="状态:"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding ConnectionStatus}" Foreground="{Binding IsConnected, Converter={StaticResource BoolToColorConverter}}"/>
|
||||
</StatusBarItem>
|
||||
<Separator/>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="流量:"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding CurrentFlow, StringFormat='{}{0:F2} L/min'}"/>
|
||||
</StatusBarItem>
|
||||
<Separator/>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="泵状态:"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding IsPumpRunning, Converter={StaticResource BoolToStringConverter}}"/>
|
||||
</StatusBarItem>
|
||||
<Separator/>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="倒计时:" Visibility="{Binding IsTesting, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding RemainingSeconds, StringFormat='{}{0} s'}" Visibility="{Binding IsTesting, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
<Border Grid.Row="0" Background="#2C3E50" CornerRadius="5" Padding="10" Margin="0,0,0,10">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="状态:" Foreground="White" FontSize="14" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding ConnectionStatus}" Foreground="{Binding IsConnected, Converter={StaticResource BoolToColorConverter}}" FontSize="14" FontWeight="Bold" Margin="5,0,20,0"/>
|
||||
<Separator Background="White" Width="1" Margin="5,0"/>
|
||||
<TextBlock Text="流量:" Foreground="White" FontSize="14" Margin="15,0,0,0"/>
|
||||
<TextBlock Text="{Binding CurrentFlow, StringFormat='{}{0:F2} L/min'}" Foreground="White" FontSize="14" FontWeight="Bold" Margin="5,0,20,0"/>
|
||||
<Separator Background="White" Width="1" Margin="5,0"/>
|
||||
<TextBlock Text="泵状态:" Foreground="White" FontSize="14" Margin="15,0,0,0"/>
|
||||
<TextBlock Text="{Binding IsPumpRunning, Converter={StaticResource BoolToStringConverter}}" Foreground="White" FontSize="14" FontWeight="Bold" Margin="5,0,20,0"/>
|
||||
<Separator Background="White" Width="1" Margin="5,0"/>
|
||||
<TextBlock Text="倒计时:" Foreground="White" FontSize="14" Margin="15,0,0,0" Visibility="{Binding IsTesting, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
<TextBlock Text="{Binding RemainingSeconds, StringFormat='{}{0} s'}" Foreground="Orange" FontSize="14" FontWeight="Bold" Margin="5,0,0,0" Visibility="{Binding IsTesting, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 实时监测参数 (Row 1) -->
|
||||
<GroupBox Header="实时监测参数" Grid.Row="1" Margin="0,5">
|
||||
<StackPanel>
|
||||
<Grid>
|
||||
<GroupBox Header="实时监测参数" Grid.Row="1" Margin="0,5" FontWeight="Bold" FontSize="14">
|
||||
<StackPanel Margin="10">
|
||||
<Grid Margin="0,5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" Orientation="Vertical">
|
||||
<TextBlock Text="流量 (L/min)" FontWeight="Bold"/>
|
||||
<TextBlock Text="{Binding RealTime.CalibratedFlow, StringFormat='{}{0:F2}'}" FontSize="18" Foreground="Blue"/>
|
||||
<TextBlock Text="(目标: 28.3)" FontSize="10" Foreground="Gray"/>
|
||||
<Border Grid.Column="0" Background="#E3F2FD" CornerRadius="8" Padding="10" Margin="5">
|
||||
<StackPanel>
|
||||
<TextBlock Text="流量 (L/min)" FontWeight="Bold" FontSize="14" TextAlignment="Center"/>
|
||||
<TextBlock Text="{Binding RealTime.CalibratedFlow, StringFormat='{}{0:F2}'}" FontSize="28" Foreground="#1565C0" TextAlignment="Center"/>
|
||||
<TextBlock Text="(目标: 28.3)" FontSize="12" Foreground="Gray" TextAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1" Orientation="Vertical">
|
||||
<TextBlock Text="温度 (℃)" FontWeight="Bold"/>
|
||||
<TextBlock Text="{Binding RealTime.Temperature, StringFormat='{}{0:F1}'}" FontSize="18"/>
|
||||
</Border>
|
||||
<Border Grid.Column="1" Background="#FFF3E0" CornerRadius="8" Padding="10" Margin="5">
|
||||
<StackPanel>
|
||||
<TextBlock Text="温度 (℃)" FontWeight="Bold" FontSize="14" TextAlignment="Center"/>
|
||||
<TextBlock Text="{Binding RealTime.Temperature, StringFormat='{}{0:F1}'}" FontSize="28" Foreground="#E65100" TextAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Orientation="Vertical">
|
||||
<TextBlock Text="泵端压力 (kPa)" FontWeight="Bold"/>
|
||||
<TextBlock Text="{Binding RealTime.PumpPressure, StringFormat='{}{0:F2}'}" FontSize="18"/>
|
||||
</Border>
|
||||
<Border Grid.Column="2" Background="#E8F5E9" CornerRadius="8" Padding="10" Margin="5">
|
||||
<StackPanel>
|
||||
<TextBlock Text="泵端压力 (kPa)" FontWeight="Bold" FontSize="14" TextAlignment="Center"/>
|
||||
<TextBlock Text="{Binding RealTime.PumpPressure, StringFormat='{}{0:F2}'}" FontSize="28" Foreground="#2E7D32" TextAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="3" Orientation="Vertical">
|
||||
<TextBlock Text="撞击器端压力 (kPa)" FontWeight="Bold"/>
|
||||
<TextBlock Text="{Binding RealTime.ImpactorPressure, StringFormat='{}{0:F2}'}" FontSize="18"/>
|
||||
</Border>
|
||||
<Border Grid.Column="3" Background="#FCE4EC" CornerRadius="8" Padding="10" Margin="5">
|
||||
<StackPanel>
|
||||
<TextBlock Text="撞击器端压力 (kPa)" FontWeight="Bold" FontSize="14" TextAlignment="Center"/>
|
||||
<TextBlock Text="{Binding RealTime.ImpactorPressure, StringFormat='{}{0:F2}'}" FontSize="28" Foreground="#C2185B" TextAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
<Separator Margin="0,5"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<TextBlock Text="压差: " FontWeight="Bold"/>
|
||||
<TextBlock Text="{Binding RealTime.DifferentialPressure, StringFormat='{}{0:F2} kPa'}" Foreground="DarkRed"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10">
|
||||
<TextBlock Text="压差: " FontWeight="Bold" FontSize="16"/>
|
||||
<TextBlock Text="{Binding RealTime.DifferentialPressure, StringFormat='{}{0:F2} kPa'}" FontSize="16" FontWeight="Bold" Foreground="#D32F2F"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 主内容 (Row 2) -->
|
||||
<Grid Grid.Row="2" Margin="0,10">
|
||||
<!-- 空调与除霜控制 (Row 2) -->
|
||||
<GroupBox Header="空调与除霜控制" Grid.Row="2" Margin="0,5" FontWeight="Bold" FontSize="14">
|
||||
<Grid Margin="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Grid.Column="0" Background="#FFF9C4" CornerRadius="8" Padding="10" Margin="5">
|
||||
<StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,5">
|
||||
<TextBlock Text="空调启动倒计时:" FontSize="14" Width="140" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding RealTime.AcStartupCountdown, StringFormat='{}{0} 秒'}" FontSize="24" FontWeight="Bold" Foreground="#F57C00"/>
|
||||
</StackPanel>
|
||||
<Separator Margin="0,10"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,5">
|
||||
<TextBlock Text="恒温启动" Width="80" FontSize="14" VerticalAlignment="Center"/>
|
||||
<ToggleButton IsChecked="{Binding RealTime.ConstantTempStart, Mode=TwoWay}"
|
||||
Command="{Binding WriteConstantTempStartCommand}"
|
||||
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}"
|
||||
IsEnabled="{Binding ConstantTempStartEnabled}"/>
|
||||
<TextBlock Text="(除霜时禁用)" FontSize="11" Foreground="Gray" Margin="10,0,0,0" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,5">
|
||||
<TextBlock Text="除霜启动" Width="80" FontSize="14" VerticalAlignment="Center"/>
|
||||
<ToggleButton IsChecked="{Binding RealTime.DefrostStart, Mode=TwoWay}"
|
||||
Command="{Binding WriteDefrostStartCommand}"
|
||||
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}"/>
|
||||
<TextBlock Text="{Binding RealTime.DefrostStart, Converter={StaticResource BoolToYesNoConverter}}" Foreground="Red" FontWeight="Bold" Margin="10,0,0,0" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Grid.Column="1" Background="#E0F2F1" CornerRadius="8" Padding="10" Margin="5">
|
||||
<StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,8">
|
||||
<TextBlock Text="除霜温度设置(℃)" Width="130" FontSize="14" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding RealTime.DefrostTempSet, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" Width="100"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,8">
|
||||
<TextBlock Text="除霜时间设置(秒)" Width="130" FontSize="14" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding RealTime.DefrostTimeSet, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" Width="100"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,8">
|
||||
<TextBlock Text="除霜计时" Width="130" FontSize="14" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding RealTime.DefrostMinute, StringFormat='{}{0}分'}" FontSize="18" FontWeight="Bold" Foreground="#00796B" Margin="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding RealTime.DefrostSecond, StringFormat='{}{0}秒'}" FontSize="18" FontWeight="Bold" Foreground="#00796B"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 主内容 (Row 3) -->
|
||||
<Grid Grid.Row="3" Margin="0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="280"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 左侧控制区 -->
|
||||
<StackPanel Grid.Column="0" Margin="5">
|
||||
<GroupBox Header="通讯控制">
|
||||
<Border Grid.Column="0" Background="White" CornerRadius="8" Padding="10" Margin="0,0,10,0" BorderBrush="#DDDDDD" BorderThickness="1">
|
||||
<StackPanel>
|
||||
<Button Command="{Binding ConnectCommand}" Content="连接PLC" Width="100" Margin="5"/>
|
||||
<Button Command="{Binding DisconnectCommand}" Content="断开连接" Width="100" Margin="5"/>
|
||||
<GroupBox Header="通讯控制" Margin="0,0,0,10">
|
||||
<StackPanel>
|
||||
<Button Command="{Binding ConnectCommand}" Content="连接PLC" Height="45"/>
|
||||
<Button Command="{Binding DisconnectCommand}" Content="断开连接" Height="45"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<GroupBox Header="采样参数" Margin="0,10">
|
||||
<GroupBox Header="采样参数" Margin="0,0,0,10">
|
||||
<StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="5">
|
||||
<TextBlock Text="采样时间(秒):" VerticalAlignment="Center" Width="100"/>
|
||||
<TextBox Text="{Binding SampleTimeSeconds}" Width="60" IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBoolConverter}}"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,5">
|
||||
<TextBlock Text="采样时间(秒):" Width="100" VerticalAlignment="Center" FontSize="14"/>
|
||||
<TextBox Text="{Binding SampleTimeSeconds}" Width="80" IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBoolConverter}}"/>
|
||||
</StackPanel>
|
||||
<Button Command="{Binding StartTestCommand}" Content="开始测试" Width="100" Margin="5"
|
||||
IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBoolConverter}}"/>
|
||||
<TextBlock Text="测试进行中..." Visibility="{Binding IsTesting, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
<Button Command="{Binding StartTestCommand}" Content="开始测试" Height="45" Margin="0,10,0,0" IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBoolConverter}}"/>
|
||||
<TextBlock Text="测试进行中..." Visibility="{Binding IsTesting, Converter={StaticResource BoolToVisibilityConverter}}" Foreground="Orange" FontWeight="Bold" FontSize="14" Margin="0,5,0,0" HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<GroupBox Header="数据分析">
|
||||
<StackPanel>
|
||||
<Button Command="{Binding CalculateCommand}" Content="计算结果" Width="100" Margin="5"/>
|
||||
<Button Command="{Binding ExportReportCommand}" Content="导出报告" Width="100" Margin="5"/>
|
||||
<Button Command="{Binding CalculateCommand}" Content="计算结果" Height="45"/>
|
||||
<Button Command="{Binding ExportReportCommand}" Content="导出报告" Height="45"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 右侧称重数据表格 -->
|
||||
<ScrollViewer Grid.Column="1" VerticalScrollBarVisibility="Auto">
|
||||
<DataGrid ItemsSource="{Binding Stages}" AutoGenerateColumns="False" CanUserAddRows="False">
|
||||
<Border Grid.Column="1" Background="White" CornerRadius="8" Padding="10" BorderBrush="#DDDDDD" BorderThickness="1">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<DataGrid ItemsSource="{Binding Stages}" AutoGenerateColumns="False" CanUserAddRows="False" IsReadOnly="False">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="层级" Binding="{Binding StageName}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="截止直径(μm)" Binding="{Binding CutoffDiameter, StringFormat='{}{0:F1}'}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="测前质量(g)" Binding="{Binding InitialWeight, StringFormat='{}{0:F4}'}"/>
|
||||
<DataGridTextColumn Header="测后质量(g)" Binding="{Binding FinalWeight, StringFormat='{}{0:F4}'}"/>
|
||||
<DataGridTextColumn Header="净重(g)" Binding="{Binding NetWeight, StringFormat='{}{0:F6}'}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="层级" Binding="{Binding StageName}" Width="80" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="截止直径(μm)" Binding="{Binding CutoffDiameter, StringFormat='{}{0:F1}'}" Width="100" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="测前质量(g)" Binding="{Binding InitialWeight, StringFormat='{}{0:F4}'}" Width="120">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="TextAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Header="测后质量(g)" Binding="{Binding FinalWeight, StringFormat='{}{0:F4}'}" Width="120">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="TextAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Header="净重(g)" Binding="{Binding NetWeight, StringFormat='{}{0:F6}'}" Width="120" IsReadOnly="True">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="TextAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- 结果显示 (Row 3) -->
|
||||
<Border Grid.Row="3" BorderBrush="Gray" BorderThickness="1" Margin="0,5,0,0" Padding="5">
|
||||
<!-- 结果显示 (Row 4) -->
|
||||
<Border Grid.Row="4" Background="#E8F5E9" CornerRadius="8" Padding="12" Margin="0,10,0,0" BorderBrush="#A5D6A7" BorderThickness="1">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<TextBlock Text="微细粒子剂量(FPD): " FontWeight="Bold"/>
|
||||
<TextBlock Text="{Binding CurrentResult.FineParticleDose, StringFormat='{}{0:F2} mg'}" Margin="5,0,20,0"/>
|
||||
<TextBlock Text="微细粒子分数(FPF): " FontWeight="Bold"/>
|
||||
<TextBlock Text="{Binding CurrentResult.FineParticleFraction, StringFormat='{}{0:F2} %'}"/>
|
||||
<TextBlock Text="微细粒子剂量(FPD): " FontWeight="Bold" FontSize="16"/>
|
||||
<TextBlock Text="{Binding CurrentResult.FineParticleDose, StringFormat='{}{0:F2} mg'}" FontSize="16" FontWeight="Bold" Foreground="#1565C0" Margin="5,0,30,0"/>
|
||||
<TextBlock Text="微细粒子分数(FPF): " FontWeight="Bold" FontSize="16"/>
|
||||
<TextBlock Text="{Binding CurrentResult.FineParticleFraction, StringFormat='{}{0:F2} %'}" FontSize="16" FontWeight="Bold" Foreground="#1565C0"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
@@ -39,5 +39,9 @@ namespace AciTester.Views
|
||||
var win = new ConfigWindow { DataContext = configVm, Owner = this };
|
||||
win.ShowDialog();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user