This commit is contained in:
xyy
2026-04-03 20:31:15 +08:00
parent 7042f94774
commit 27780b99f3
2 changed files with 137 additions and 12 deletions

View File

@@ -1,10 +1,59 @@
namespace MembranePoreTester.Models
{
public class DataPoint
{
public double Pressure { get; set; } // 压力
public double WetFlow { get; set; } // 湿膜流量(L/min)
public double DryFlow { get; set; } // 干膜流量(L/min)
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MembranePoreTester.Models
{
// 数据点实现 INotifyPropertyChanged保证 UIDataGrid/Plot在属性变化时刷新
public class DataPoint : INotifyPropertyChanged
{
private double _pressure;
private double _wetFlow;
private double _dryFlow;
public double Pressure
{
get => _pressure;
set
{
if (_pressure != value)
{
_pressure = value;
OnPropertyChanged();
}
}
}
public double WetFlow
{
get => _wetFlow;
set
{
if (_wetFlow != value)
{
_wetFlow = value;
OnPropertyChanged();
}
}
}
public double DryFlow
{
get => _dryFlow;
set
{
if (_dryFlow != value)
{
_dryFlow = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

View File

@@ -9,6 +9,8 @@ using OxyPlot.Legends;
using OxyPlot.Series;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
@@ -138,7 +140,7 @@ namespace MembranePoreTester.ViewModels
{
// 清空数据点集合
Record.DataPoints.Clear();
PlotModel = new PlotModel();
// 重置曲线
UpdatePlot();
@@ -186,7 +188,14 @@ namespace MembranePoreTester.ViewModels
public PoreDistributionRecord Record
{
get => _record;
set => SetProperty(ref _record, value);
set
{
if (SetProperty(ref _record, value))
{
// 当 Record 替换时(例如从数据库加载),重新订阅其 DataPoints 集合
HookDataPointsCollection(_record?.DataPoints);
}
}
}
public List<TestLiquid> Liquids => TestLiquid.Predefined;
@@ -270,7 +279,8 @@ namespace MembranePoreTester.ViewModels
OpenFlowCalibCommand = new RelayCommand(OpenFlowCalibration);
OpenFlowCalibCommand2 = new RelayCommand(OpenFlowCalibration2);
Record.DataPoints.CollectionChanged += (s, e) => UpdatePlot();
// 订阅集合变更并为每个项订阅属性变化,保证 DataGrid 和 Plot 在项内容变化时同步刷新
HookDataPointsCollection(Record.DataPoints);
ClearAllCommand = new RelayCommand(ClearAllData);
@@ -440,6 +450,59 @@ namespace MembranePoreTester.ViewModels
}
}
// 监听 DataPoints 集合与其子项的属性变更,确保 UI 同步更新
private void HookDataPointsCollection(ObservableCollection<Models.DataPoint> collection)
{
if (collection == null) return;
// 先解绑已有(避免重复订阅)
collection.CollectionChanged -= DataPoints_CollectionChanged;
collection.CollectionChanged += DataPoints_CollectionChanged;
// 为已有项订阅 PropertyChanged
foreach (var item in collection)
{
if (item is INotifyPropertyChanged inpc)
{
inpc.PropertyChanged -= DataPoint_PropertyChanged;
inpc.PropertyChanged += DataPoint_PropertyChanged;
}
}
}
private void DataPoints_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
{
foreach (var old in e.OldItems)
{
if (old is INotifyPropertyChanged inpc)
inpc.PropertyChanged -= DataPoint_PropertyChanged;
}
}
if (e.NewItems != null)
{
foreach (var nw in e.NewItems)
{
if (nw is INotifyPropertyChanged inpc)
{
inpc.PropertyChanged -= DataPoint_PropertyChanged;
inpc.PropertyChanged += DataPoint_PropertyChanged;
}
}
}
// 集合结构变化时刷新曲线
UpdatePlot();
}
private void DataPoint_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
// 某个数据点属性改变时也刷新曲线
UpdatePlot();
}
// 添加私有字段和公共属性
private double _averagePoreSize;
public double AveragePoreSize
@@ -681,6 +744,9 @@ namespace MembranePoreTester.ViewModels
set => SetProperty(ref _plotModel, value);
}
// 用于保护绘图更新,避免并发导致渲染丢失
private readonly object _plotLock = new();
private async Task WriteFlowModeAsync(string mode)
{
ushort val = mode.ToString().Contains("大流量") ? (ushort)0 : (ushort)1;
@@ -698,6 +764,13 @@ namespace MembranePoreTester.ViewModels
private void UpdatePlot()
{
// Ensure we run on UI thread because we update PlotModel (bound to UI)
if (Application.Current != null && !Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.BeginInvoke((Action)UpdatePlot);
return;
}
var sorted = Record.DataPoints.OrderBy(p => p.Pressure).ToList();
if (sorted.Count == 0)
{
@@ -762,7 +835,10 @@ namespace MembranePoreTester.ViewModels
model.Series.Add(wetSeries);
model.Series.Add(drySeries);
PlotModel = model;
lock (_plotLock)
{
PlotModel = model;
}
}