This commit is contained in:
xyy
2026-04-10 18:01:18 +08:00
parent 90035eb8df
commit 61c5e9f006
3 changed files with 246 additions and 67 deletions

View File

@@ -67,24 +67,33 @@ namespace MembranePoreTester.ViewModels
private bool _isCollecting = false;
// 添加公共方法供工位调用
//public void StartCollecting()
//{
// System.Diagnostics.Debug.WriteLine($"StartCollecting 工位{StationId}, IsActive={IsActive}");
// //if (!IsActive)
// //{
// // // 如果当前不在孔分布界面,不启动采集
// // return;
// //}
// if (_isCollecting) return;
// _isCollecting = true;
// _autoCollectTimer = new System.Windows.Threading.DispatcherTimer
// {
// Interval = TimeSpan.FromSeconds(1)
// };
// _autoCollectTimer.Tick += AutoCollectTimer_Tick;
// _autoCollectTimer.Start();
//}
public void StartCollecting()
{
if (!IsActive)
{
// 如果当前不在孔分布界面,不启动采集
return;
}
// 不再依赖 IsActive定时器始终启动
if (_isCollecting) return;
_isCollecting = true;
_autoCollectTimer = new System.Windows.Threading.DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
_autoCollectTimer = new System.Windows.Threading.DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_autoCollectTimer.Tick += AutoCollectTimer_Tick;
_autoCollectTimer.Start();
}
public void StopCollecting()
{
_isCollecting = false;
@@ -94,7 +103,7 @@ namespace MembranePoreTester.ViewModels
private async void AutoCollectTimer_Tick(object sender, EventArgs e)
{
//if (!IsActive) return;
if (!IsActive) return;
try
{
@@ -762,7 +771,7 @@ namespace MembranePoreTester.ViewModels
StationId = this.StationId,
TestDate = Record.TestDate,
Tester = Record.Tester ?? "系统操作员",
SampleType = Record.SampleType,
SampleType = Record.SampleType ?? "膜类型缺省值",
SampleSpec = Record.SampleSpec ?? "缺省值",
RoomTemperature = Record.RoomTemperature,
SoakingTime = Record.SoakingTime,
@@ -924,9 +933,111 @@ namespace MembranePoreTester.ViewModels
//private void UpdatePlot()
//{
// // 确保在 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)
// {
// PlotModel = null;
// return;
// }
// var model = new PlotModel
// {
// Title = "流量-压力曲线",
// TitleFontSize = 14,
// TitleFontWeight = 1
// };
// model.Axes.Add(new LinearAxis
// {
// Position = AxisPosition.Bottom,
// Title = "压力 (kPa)",
// TitleFontSize = 12
// });
// model.Axes.Add(new LinearAxis
// {
// Position = AxisPosition.Left,
// Title = "流量 (L/min)",
// TitleFontSize = 12,
// Minimum = 0,
// MajorGridlineStyle = LineStyle.Solid,
// MinorGridlineStyle = LineStyle.Dot
// });
// // 根据当前模式绘制对应的曲线(只绘制流量 > 0 的点)
// if (TestMode != null && TestMode.Contains("湿膜"))
// {
// var wetSeries = new LineSeries
// {
// Title = "湿膜流量 (Wet Flow)",
// Color = OxyColors.Blue,
// MarkerType = MarkerType.None,
// StrokeThickness = 1
// };
// foreach (var dp in sorted.Where(p => p.WetFlow > 0))
// wetSeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.WetFlow));
// if (wetSeries.Points.Count > 0)
// model.Series.Add(wetSeries);
// }
// else if (TestMode != null && TestMode.Contains("干膜"))
// {
// var drySeries = new LineSeries
// {
// Title = "干膜流量 (Dry Flow)",
// Color = OxyColors.Red,
// MarkerType = MarkerType.None,
// StrokeThickness = 1
// };
// foreach (var dp in sorted.Where(p => p.DryFlow > 0))
// drySeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.DryFlow));
// if (drySeries.Points.Count > 0)
// model.Series.Add(drySeries);
// }
// else
// {
// // “全部”模式:同时显示两条曲线,但仍过滤掉 0 值点
// var wetSeries = new LineSeries
// {
// Title = "湿膜流量 (Wet Flow)",
// Color = OxyColors.Blue,
// MarkerType = MarkerType.None,
// StrokeThickness = 1
// };
// var drySeries = new LineSeries
// {
// Title = "干膜流量 (Dry Flow)",
// Color = OxyColors.Red,
// MarkerType = MarkerType.None,
// StrokeThickness = 1
// };
// foreach (var dp in sorted)
// {
// if (dp.WetFlow > 0) wetSeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.WetFlow));
// if (dp.DryFlow > 0) drySeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.DryFlow));
// }
// if (wetSeries.Points.Count > 0) model.Series.Add(wetSeries);
// if (drySeries.Points.Count > 0) model.Series.Add(drySeries);
// }
// PlotModel = model;
//}
private void UpdatePlot()
{
// Ensure we run on UI thread because we update PlotModel (bound to UI)
// 确保在 UI 线程执行
if (Application.Current != null && !Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.BeginInvoke((Action)UpdatePlot);
@@ -947,81 +1058,100 @@ namespace MembranePoreTester.ViewModels
TitleFontWeight = 1
};
// 让线条更平滑使用线性插值OxyPlot 默认即可),同时关闭区域填充等
model.DefaultColors = new[] { OxyColors.Blue, OxyColors.Red };
// 添加坐标轴
model.Axes.Add(new LinearAxis
{
Position = AxisPosition.Bottom,
Title = "压力 (kPa)",
TitleFontSize = 12
});
model.Axes.Add(new LinearAxis
{
Position = AxisPosition.Left,
Title = "流量 (L/min)",
TitleFontSize = 12,
Minimum = 0, // 从0开始绘制避免覆盖整个Y轴
Minimum = 0,
MajorGridlineStyle = LineStyle.Solid,
MinorGridlineStyle = LineStyle.Dot
});
// 湿膜流量 - 使用更清晰的标题
var wetSeries = new LineSeries
// 干膜半流量曲线(绿色虚线,每个压力点干膜流量的一半)
var halfDrySeries = new LineSeries
{
Title = "湿膜流量 (Wet Flow)",
Color = OxyColors.Blue,
Title = "干膜半流量 (Half of Dry Flow)",
Color = OxyColors.Green,
MarkerType = MarkerType.None,
StrokeThickness = 1
StrokeThickness = 1,
LineStyle = LineStyle.Dash
};
// 干膜流量 - 使用更清晰的标题
var drySeries = new LineSeries
foreach (var dp in sorted.Where(p => p.DryFlow > 0))
{
Title = "干膜流量 (Dry Flow)",
Color = OxyColors.Red,
MarkerType = MarkerType.None,
StrokeThickness = 1
};
// 始终按记录填充两个序列(保留历史数据),但只在当前测试模式下将对应序列添加到图表
foreach (var dp in sorted)
{
wetSeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.WetFlow));
drySeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.DryFlow));
halfDrySeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.DryFlow / 2.0));
}
// 根据当前 TestMode 决定显示哪条曲线,切换回另一种模式时其历史数据会从 Record 恢复并显示
// 根据当前模式绘制对应的曲线(只绘制流量 > 0 的点)
if (TestMode != null && TestMode.Contains("湿膜"))
{
var wetSeries = new LineSeries
{
Title = "湿膜流量 (Wet Flow)",
Color = OxyColors.Blue,
MarkerType = MarkerType.None,
StrokeThickness = 1
};
foreach (var dp in sorted.Where(p => p.WetFlow > 0))
wetSeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.WetFlow));
if (wetSeries.Points.Count > 0)
model.Series.Add(wetSeries);
// 湿膜模式下也显示半流量线(便于观察交点)
if (halfDrySeries.Points.Count > 0)
model.Series.Add(halfDrySeries);
}
else if (TestMode != null && TestMode.Contains("干膜"))
{
var drySeries = new LineSeries
{
Title = "干膜流量 (Dry Flow)",
Color = OxyColors.Red,
MarkerType = MarkerType.None,
StrokeThickness = 1
};
foreach (var dp in sorted.Where(p => p.DryFlow > 0))
drySeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.DryFlow));
if (drySeries.Points.Count > 0)
model.Series.Add(drySeries);
if (halfDrySeries.Points.Count > 0)
model.Series.Add(halfDrySeries);
}
else
{
// 如果没有明确模式,默认显示两条曲线(适用于同时显示的情况)
if (wetSeries.Points.Count > 0)
model.Series.Add(wetSeries);
if (drySeries.Points.Count > 0)
model.Series.Add(drySeries);
// “全部”模式:同时显示两条曲线,但仍过滤掉 0 值点
var wetSeries = new LineSeries
{
Title = "湿膜流量 (Wet Flow)",
Color = OxyColors.Blue,
MarkerType = MarkerType.None,
StrokeThickness = 1
};
var drySeries = new LineSeries
{
Title = "干膜流量 (Dry Flow)",
Color = OxyColors.Red,
MarkerType = MarkerType.None,
StrokeThickness = 1
};
foreach (var dp in sorted)
{
if (dp.WetFlow > 0) wetSeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.WetFlow));
if (dp.DryFlow > 0) drySeries.Points.Add(new OxyPlot.DataPoint(dp.Pressure, dp.DryFlow));
}
if (wetSeries.Points.Count > 0) model.Series.Add(wetSeries);
if (drySeries.Points.Count > 0) model.Series.Add(drySeries);
if (halfDrySeries.Points.Count > 0) model.Series.Add(halfDrySeries);
}
lock (_plotLock)
{
PlotModel = model;
}
PlotModel = model;
}
public ICommand ClearAllCommand { get; }

View File

@@ -261,9 +261,17 @@
<TextBlock Text="湿膜流量 (Wet Flow)" FontSize="11" Margin="0,0,15,0"/>
<Rectangle Width="20" Height="2" Fill="Red" Margin="0,0,5,0"/>
<TextBlock Text="干膜流量 (Dry Flow)" FontSize="11"/>
<!-- 新增:干膜半流量标注(绿色虚线) -->
<Rectangle Width="20" Height="2" Fill="Green" Margin="10,0,5,0"/>
<TextBlock Text="干膜半流量 (Half of Dry Flow)" FontSize="11"/>
</StackPanel>
</Border>
<oxy:PlotView Model="{Binding PlotModel}" Height="300" Margin="5"/>
<!--<oxy:PlotView Model="{Binding PlotModel}" Height="300" Margin="5"/>-->
<oxy:PlotView x:Name="PlotViewStation1" Height="300" Margin="5" Visibility="Collapsed"/>
<oxy:PlotView x:Name="PlotViewStation2" Height="300" Margin="5" Visibility="Collapsed"/>
<oxy:PlotView x:Name="PlotViewStation3" Height="300" Margin="5" Visibility="Collapsed"/>
</StackPanel>
</GroupBox>
</Grid>

View File

@@ -6,51 +6,92 @@ namespace MembranePoreTester.Views
{
public partial class PoreDistributionView : UserControl
{
private MainViewModel _mainVM;
public PoreDistributionView()
{
InitializeComponent();
//DataContext = new ViewModels.PoreDistributionViewModel();
// 监听 IsVisible 变化
this.IsVisibleChanged += (s, e) =>
{
if (this.DataContext is ViewModels.PoreDistributionViewModel vm)
if (this.DataContext is PoreDistributionViewModel vm)
{
System.Diagnostics.Debug.WriteLine($"工位{vm.StationId} IsVisible={this.IsVisible}");
vm.IsActive = this.IsVisible;
if (!this.IsVisible)
{
// 离开孔分布界面时,停止自动采集
//vm.StopCollecting();
}
}
};
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
// 保留原有滚动功能
var vm = this.DataContext as PoreDistributionViewModel;
if (vm != null)
{
vm.Record.DataPoints.CollectionChanged += DataPoints_CollectionChanged;
}
// 获取主窗口 ViewModel
_mainVM = Application.Current.MainWindow?.DataContext as MainViewModel;
if (_mainVM == null) return;
// 为每个工位订阅 PropertyChanged实时更新对应的 PlotView 模型
for (int i = 0; i < _mainVM.Stations.Count; i++)
{
int stationId = i + 1;
var stationVm = _mainVM.Stations[i].PoreDistributionVM;
stationVm.PropertyChanged += (s, ev) =>
{
if (ev.PropertyName == nameof(PoreDistributionViewModel.PlotModel))
{
Dispatcher.Invoke(() =>
{
switch (stationId)
{
case 1: PlotViewStation1.Model = stationVm.PlotModel; break;
case 2: PlotViewStation2.Model = stationVm.PlotModel; break;
case 3: PlotViewStation3.Model = stationVm.PlotModel; break;
}
});
}
};
// 初始化当前模型
if (stationVm.PlotModel != null)
{
switch (stationId)
{
case 1: PlotViewStation1.Model = stationVm.PlotModel; break;
case 2: PlotViewStation2.Model = stationVm.PlotModel; break;
case 3: PlotViewStation3.Model = stationVm.PlotModel; break;
}
}
}
// 监听当前 DataContext 变化,切换可见性
this.DataContextChanged += (s, ev) => UpdateVisibility();
UpdateVisibility();
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
private void UpdateVisibility()
{
if (this.DataContext is PoreDistributionViewModel vm)
{
PlotViewStation1.Visibility = vm.StationId == 1 ? Visibility.Visible : Visibility.Collapsed;
PlotViewStation2.Visibility = vm.StationId == 2 ? Visibility.Visible : Visibility.Collapsed;
PlotViewStation3.Visibility = vm.StationId == 3 ? Visibility.Visible : Visibility.Collapsed;
}
}
private void Button_Click(object sender, RoutedEventArgs e) { }
private void DataPoints_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
// 滚动湿膜表格到底部
ScrollDataGridToEnd(dgWetData);
// 滚动干膜表格到底部
ScrollDataGridToEnd(dgDryData);
}
}