更新
This commit is contained in:
@@ -328,7 +328,7 @@
|
||||
|
||||
<Grid Background="{StaticResource ShellGradientBrush}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="SidebarColumn" Width="118" />
|
||||
<ColumnDefinition Width="360" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
@@ -337,7 +337,7 @@
|
||||
Background="{StaticResource SidebarBrush}"
|
||||
BorderBrush="#B9C7D1"
|
||||
BorderThickness="0,0,1,0"
|
||||
Padding="12">
|
||||
Padding="18,16,14,16">
|
||||
<Grid>
|
||||
<ScrollViewer x:Name="SidebarDetails"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
@@ -346,21 +346,10 @@
|
||||
<Border Style="{StaticResource PanelBorderStyle}"
|
||||
Background="{StaticResource SurfaceRaisedBrush}"
|
||||
Margin="0,0,0,14">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" Margin="0,0,12,0">
|
||||
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="试验参数" />
|
||||
<TextBlock Style="{StaticResource SectionHintStyle}" Text="参数编辑保留在侧栏,主界面聚焦控制、曲线和结果。" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1"
|
||||
Width="88"
|
||||
Style="{StaticResource GhostButtonStyle}"
|
||||
Click="ToggleSidebar_Click"
|
||||
Content="收起" />
|
||||
</Grid>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource SectionTitleStyle}" Text="试验参数" />
|
||||
<TextBlock Style="{StaticResource SectionHintStyle}" Text="参数编辑保留在侧栏,主界面聚焦控制、曲线和结果。" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource PanelBorderStyle}"
|
||||
@@ -505,48 +494,6 @@
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<Grid x:Name="SidebarCollapsedRail" Visibility="Collapsed">
|
||||
<Border Style="{StaticResource PanelBorderStyle}"
|
||||
Background="{StaticResource SurfaceRaisedBrush}"
|
||||
Padding="10">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Button Width="52"
|
||||
Height="42"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,12"
|
||||
Style="{StaticResource GhostButtonStyle}"
|
||||
Click="ToggleSidebar_Click"
|
||||
Content=">" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Text="参数" />
|
||||
<Border Height="4"
|
||||
Margin="8,14,8,14"
|
||||
Background="{StaticResource AccentStripBrush}"
|
||||
CornerRadius="2" />
|
||||
<Border Style="{StaticResource InsetCardStyle}" Padding="10">
|
||||
<StackPanel>
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Style="{StaticResource CaptionStyle}"
|
||||
Text="状态" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding MachineState, Mode=OneWay}" />
|
||||
<TextBlock Margin="0,10,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Style="{StaticResource CaptionStyle}"
|
||||
Text="{Binding Recipe.BatchNumber, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<TextBlock Margin="0,14,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Style="{StaticResource SectionHintStyle}"
|
||||
Text="展开编辑" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
@@ -767,8 +714,11 @@
|
||||
|
||||
<Border Grid.Column="0"
|
||||
Style="{StaticResource PanelBorderStyle}"
|
||||
Margin="0,0,16,0">
|
||||
<Grid>
|
||||
Margin="0,0,16,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
@@ -784,13 +734,20 @@
|
||||
BorderBrush="#C2D0D9"
|
||||
BorderThickness="1"
|
||||
CornerRadius="14"
|
||||
Padding="8">
|
||||
Padding="8"
|
||||
MinHeight="360"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Border Background="{StaticResource ChartSurfaceBrush}"
|
||||
BorderBrush="#98A9B7"
|
||||
BorderThickness="1"
|
||||
CornerRadius="10"
|
||||
Padding="6">
|
||||
Padding="8,8,8,18"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<lvc:CartesianChart x:Name="RealtimeForceChart"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Series="{Binding ForceSeries}"
|
||||
XAxes="{Binding ForceXAxes}"
|
||||
YAxes="{Binding ForceYAxes}"
|
||||
|
||||
@@ -4,22 +4,20 @@ using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using COFTester.ViewModels;
|
||||
using LiveChartsCore.Kernel;
|
||||
|
||||
namespace COFTester;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private const double ExpandedSidebarWidth = 360;
|
||||
private const double CollapsedSidebarWidth = 118;
|
||||
private readonly MainViewModel _viewModel = new();
|
||||
private bool _isSidebarCollapsed;
|
||||
private bool _isRealtimeChartLayoutRefreshQueued;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = _viewModel;
|
||||
SetSidebarCollapsed(true);
|
||||
QueueRealtimeChartLayoutRefresh();
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
@@ -28,9 +26,16 @@ public partial class MainWindow : Window
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
private void ToggleSidebar_Click(object sender, RoutedEventArgs e)
|
||||
protected override void OnContentRendered(EventArgs e)
|
||||
{
|
||||
SetSidebarCollapsed(!_isSidebarCollapsed);
|
||||
base.OnContentRendered(e);
|
||||
QueueRealtimeChartLayoutRefresh();
|
||||
}
|
||||
|
||||
protected override void OnStateChanged(EventArgs e)
|
||||
{
|
||||
base.OnStateChanged(e);
|
||||
QueueRealtimeChartLayoutRefresh();
|
||||
}
|
||||
|
||||
private void ShowRealtimeTab_Click(object sender, RoutedEventArgs e)
|
||||
@@ -96,16 +101,6 @@ public partial class MainWindow : Window
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSidebarCollapsed(bool collapsed)
|
||||
{
|
||||
_isSidebarCollapsed = collapsed;
|
||||
SidebarColumn.Width = new GridLength(collapsed ? CollapsedSidebarWidth : ExpandedSidebarWidth);
|
||||
SidebarDetails.Visibility = collapsed ? Visibility.Collapsed : Visibility.Visible;
|
||||
SidebarCollapsedRail.Visibility = collapsed ? Visibility.Visible : Visibility.Collapsed;
|
||||
SidebarHost.Padding = collapsed ? new Thickness(12) : new Thickness(18, 16, 14, 16);
|
||||
QueueRealtimeChartLayoutRefresh();
|
||||
}
|
||||
|
||||
private void QueueRealtimeChartLayoutRefresh()
|
||||
{
|
||||
if (_isRealtimeChartLayoutRefreshQueued)
|
||||
@@ -114,13 +109,25 @@ public partial class MainWindow : Window
|
||||
}
|
||||
|
||||
_isRealtimeChartLayoutRefreshQueued = true;
|
||||
Dispatcher.BeginInvoke(RefreshRealtimeChartLayout, DispatcherPriority.ContextIdle);
|
||||
Dispatcher.BeginInvoke(RunRealtimeChartLayoutRefreshSequence, DispatcherPriority.Loaded);
|
||||
}
|
||||
|
||||
private void RunRealtimeChartLayoutRefreshSequence()
|
||||
{
|
||||
RefreshRealtimeChartLayout();
|
||||
Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
RefreshRealtimeChartLayout();
|
||||
Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
RefreshRealtimeChartLayout();
|
||||
_isRealtimeChartLayoutRefreshQueued = false;
|
||||
}, DispatcherPriority.ApplicationIdle);
|
||||
}, DispatcherPriority.Render);
|
||||
}
|
||||
|
||||
private void RefreshRealtimeChartLayout()
|
||||
{
|
||||
_isRealtimeChartLayoutRefreshQueued = false;
|
||||
|
||||
if (RealtimeForceChart.ActualWidth <= 0 || RealtimeForceChart.ActualHeight <= 0)
|
||||
{
|
||||
return;
|
||||
@@ -129,5 +136,10 @@ public partial class MainWindow : Window
|
||||
RealtimeForceChart.InvalidateMeasure();
|
||||
RealtimeForceChart.InvalidateArrange();
|
||||
RealtimeForceChart.UpdateLayout();
|
||||
RealtimeForceChart.CoreChart.Update(new ChartUpdateParams
|
||||
{
|
||||
IsAutomaticUpdate = false,
|
||||
Throttling = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,9 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
private static readonly TimeSpan RealtimeChartRefreshInterval = TimeSpan.FromMilliseconds(250);
|
||||
private const double RealtimeChartDisplacementStepMm = 0.5;
|
||||
private const double RealtimeChartXAxisPaddingMm = 5;
|
||||
private const double MinimumEmptyChartXAxisMaxLimit = 1;
|
||||
private const double EmptyChartYAxisMaxLimit = 0.5;
|
||||
private const double EmptyChartPointForceN = 0.001;
|
||||
|
||||
private readonly DispatcherTimer _timer;
|
||||
private readonly DispatcherTimer _deviceReconnectTimer;
|
||||
@@ -231,8 +234,8 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
}
|
||||
];
|
||||
|
||||
_lastForceXAxisMaxLimit = 1;
|
||||
_lastForceYAxisMaxLimit = 0.5;
|
||||
_lastForceXAxisMaxLimit = GetEmptyChartXAxisMaxLimit();
|
||||
_lastForceYAxisMaxLimit = EmptyChartYAxisMaxLimit;
|
||||
ForceXAxes = CreateForceXAxes(_lastForceXAxisMaxLimit);
|
||||
ForceYAxes = CreateForceYAxes(_lastForceYAxisMaxLimit);
|
||||
|
||||
@@ -241,13 +244,14 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
Xi = Recipe.TravelMm * 0.35,
|
||||
Xj = Recipe.TravelMm,
|
||||
Yi = 0,
|
||||
Yj = 1,
|
||||
Yj = EmptyChartYAxisMaxLimit,
|
||||
Fill = new SolidColorPaint(new SKColor(0, 105, 180, 18)),
|
||||
Stroke = new SolidColorPaint(new SKColor(0, 105, 180, 70), 1)
|
||||
};
|
||||
|
||||
ForceSections = [_kineticBand];
|
||||
|
||||
ShowEmptyRealtimeChartFrame();
|
||||
LoadHistoryFromDatabase();
|
||||
UpdateDerivedValues();
|
||||
AddInfoEvent("系统启动,正在初始化 PLC 通信与本地数据存储。");
|
||||
@@ -1262,7 +1266,7 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
NamePaint = new SolidColorPaint(new SKColor(33, 49, 61)),
|
||||
SeparatorsPaint = new SolidColorPaint(new SKColor(209, 219, 227), 1),
|
||||
SubseparatorsPaint = new SolidColorPaint(new SKColor(229, 236, 242), 1),
|
||||
Padding = new Padding(8, 0, 0, 0)
|
||||
Padding = new Padding(8, 0, 12, 8)
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -1661,10 +1665,43 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentPointSample.Clear();
|
||||
ShowEmptyRealtimeChartFrame();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowEmptyRealtimeChartFrame()
|
||||
{
|
||||
_forceSamples.Clear();
|
||||
_peakLineSamples.Clear();
|
||||
_averageLineSamples.Clear();
|
||||
_currentPointSample.Clear();
|
||||
_currentPointSample.Add(new ObservablePoint(0, EmptyChartPointForceN));
|
||||
SetAxisLimits(GetEmptyChartXAxisMaxLimit(), EmptyChartYAxisMaxLimit);
|
||||
_kineticBand.Xi = Recipe.TravelMm * 0.35;
|
||||
_kineticBand.Xj = Recipe.TravelMm;
|
||||
_kineticBand.Yi = 0;
|
||||
_kineticBand.Yj = EmptyChartYAxisMaxLimit;
|
||||
OnPropertyChanged(nameof(ForceSections));
|
||||
}
|
||||
|
||||
private void RefreshEmptyRealtimeChartFrameIfVisible()
|
||||
{
|
||||
if (_machineRuntimeState != MachineRuntimeState.Idle ||
|
||||
_isShowingHistoricalRun ||
|
||||
_currentRunSamples.Count > 0 ||
|
||||
_forceSamples.Count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShowEmptyRealtimeChartFrame();
|
||||
}
|
||||
|
||||
private double GetEmptyChartXAxisMaxLimit()
|
||||
{
|
||||
return Math.Max(Recipe.TravelMm, MinimumEmptyChartXAxisMaxLimit);
|
||||
}
|
||||
|
||||
private void ResetRealtimePresentation()
|
||||
{
|
||||
_forceSamples.Clear();
|
||||
@@ -1692,13 +1729,7 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
CurrentKineticCoefficient = 0;
|
||||
TrialProgressPercent = 0;
|
||||
|
||||
SetAxisLimits(1, 0.5);
|
||||
_kineticBand.Xi = Recipe.TravelMm * 0.35;
|
||||
_kineticBand.Xj = Recipe.TravelMm;
|
||||
_kineticBand.Yi = 0;
|
||||
_kineticBand.Yj = 0.5;
|
||||
|
||||
OnPropertyChanged(nameof(ForceSections));
|
||||
ShowEmptyRealtimeChartFrame();
|
||||
}
|
||||
|
||||
private void ResetActiveRunContext()
|
||||
@@ -1799,6 +1830,12 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
{
|
||||
AddWarningEvent($"测试参数写入 PLC 失败 {e.PropertyName}: {ex.Message}");
|
||||
}
|
||||
|
||||
if (e.PropertyName == nameof(TestRecipe.TravelMm))
|
||||
{
|
||||
RefreshEmptyRealtimeChartFrameIfVisible();
|
||||
RaiseStatusProperties();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SyncRecipeFromPlcAsync()
|
||||
@@ -1830,6 +1867,9 @@ public sealed class MainViewModel : ObservableObject, IDisposable
|
||||
{
|
||||
_isSyncingRecipeFromPlc = false;
|
||||
}
|
||||
|
||||
RefreshEmptyRealtimeChartFrameIfVisible();
|
||||
RaiseStatusProperties();
|
||||
}
|
||||
|
||||
private async Task SyncRecipePropertyToPlcAsync(string propertyName)
|
||||
|
||||
Reference in New Issue
Block a user