Files
VacuumPressureMembranePoreS…/Views/ParameterWindow.xaml.cs
2026-04-02 14:34:29 +08:00

175 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using MembranePoreTester.Communication;
using MembranePoreTester.ViewModels;
namespace MembranePoreTester.Views
{
public partial class ParameterWindow : Window
{
private readonly IPlcService _plcService;
private readonly PlcConfiguration _config;
private DispatcherTimer _autoRefreshTimer;
// 用于快速查找文本框对应的写入地址和方法(可根据需要扩展)
private readonly Dictionary<TextBox, (ushort address, string paramName)> _textBoxMapping;
public ParameterWindow()
{
InitializeComponent();
_plcService = App.PlcService;
_config = App.PlcConfig;
// 初始化文本框到寄存器地址的映射
_textBoxMapping = new Dictionary<TextBox, (ushort, string)>
{
//[txtPressureUpper] = (_config.PressureUpperLimit, "加压上限"),
//[txtPressureRate] = (_config.PressureRate, "加压速率"),
//[txtPressureCoeff] = (_config.PressureCoeff, "加压系数"),
//[txtHPCoeff11] = (_config.HPCoeff11, "工位1加压速率"),
[txtHPCoeff1] = (_config.HPCoeff1, "工位1高压系数"),
[txtLPCoeff1] = (_config.LPCoeff1, "工位1低压系数"),
[txtHPCoeff2] = (_config.HPCoeff2, "工位2高压系数"),
[txtLPCoeff2] = (_config.LPCoeff2, "工位2低压系数"),
[txtHPCoeff3] = (_config.HPCoeff3, "工位3高压系数"),
[txtLPCoeff3] = (_config.LPCoeff3, "工位3低压系数"),
[txtLargeFlow1] = (_config.LargeFlowCoeff1, "工位1大流量系数"),
[txtSmallFlow1] = (_config.SmallFlowCoeff1, "工位1小流量系数"),
[txtLargeFlow2] = (_config.LargeFlowCoeff2, "工位2大流量系数"),
[txtSmallFlow2] = (_config.SmallFlowCoeff2, "工位2小流量系数"),
[txtLargeFlow3] = (_config.LargeFlowCoeff3, "工位3大流量系数"),
[txtSmallFlow3] = (_config.SmallFlowCoeff3, "工位3小流量系数"),
//[txtPressureZero] = (_config.PressureCalibZero, "压力零点"),
//[txtPressureSpan] = (_config.PressureCalibSpan, "压力量程"),
//[txtFlowZero] = (_config.FlowCalibZero, "流量零点"),
//[txtFlowSpan] = (_config.FlowCalibSpan, "流量量程"),
};
// 为所有文本框注册焦点事件
RegisterTextBoxEvents();
Loaded += async (s, e) =>
{
// 启动定时器
_autoRefreshTimer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
_autoRefreshTimer.Tick += AutoRefreshTimer_Tick;
_autoRefreshTimer.Start();
// 首次加载时读取一次
await LoadParameters();
};
Closed += (s, e) => _autoRefreshTimer?.Stop();
}
private void RegisterTextBoxEvents()
{
foreach (var tb in _textBoxMapping.Keys)
{
tb.GotFocus += (s, e) => { /* 什么都不做,只是为了让自动刷新跳过当前焦点的文本框 */ };
tb.LostFocus += async (s, e) =>
{
// 失去焦点时将当前文本框的值写入PLC
var (address, name) = _textBoxMapping[tb];
if (float.TryParse(tb.Text, out float value))
{
try
{
await WriteFloatAsync(address, value);
// 可选:显示短暂提示(避免频繁弹窗)
System.Diagnostics.Debug.WriteLine($"{name} 已写入: {value}");
}
catch (Exception ex)
{
MessageBox.Show($"写入 {name} 失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
else
{
// 输入无效,可提示或恢复原值
MessageBox.Show($"请输入有效的数值", "输入错误", MessageBoxButton.OK, MessageBoxImage.Warning);
// 重新从PLC读取该参数恢复原值
await UpdateSingleTextBox(tb, address);
}
};
}
}
/// <summary>
/// 更新单个文本框的值从PLC读取
/// </summary>
private async Task UpdateSingleTextBox(TextBox tb, ushort address)
{
try
{
float val = await ReadFloatAsync(address);
tb.Text = val.ToString("F3");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"更新文本框失败: {ex.Message}");
}
}
private async void AutoRefreshTimer_Tick(object sender, EventArgs e)
{
// 只更新当前没有获得焦点的文本框
await Dispatcher.InvokeAsync(async () =>
{
foreach (var kv in _textBoxMapping)
{
var tb = kv.Key;
var address = kv.Value.address;
if (!tb.IsFocused)
{
try
{
float val = await ReadFloatAsync(address);
tb.Text = val.ToString("F3");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"自动刷新 {kv.Value.paramName} 失败: {ex.Message}");
}
}
}
});
}
/// <summary>
/// 一次性加载所有参数(用于窗口启动)
/// </summary>
private async Task LoadParameters()
{
foreach (var kv in _textBoxMapping)
{
await UpdateSingleTextBox(kv.Key, kv.Value.address);
}
}
// 以下方法与之前相同但保留用于写入已在LostFocus中调用
private async Task<float> ReadFloatAsync(ushort address)
{
var registers = await ((ModbusTcpPlcService)_plcService).ReadHoldingRegistersAsync(address, 2);
return ((ModbusTcpPlcService)_plcService).UshortToFloat(registers[1], registers[0]);
}
private async Task WriteFloatAsync(ushort address, float value)
{
await ((ModbusTcpPlcService)_plcService).WriteMultipleRegistersAsync(address, value);
}
private void Close_Click(object sender, RoutedEventArgs e) => Close();
}
}