feat: redesign Pump page with Fluent card layout, bottom snackbar, and RPM chart
- Replace sub-nav + HiddenTabsTabControl with 3-column Fluent card layout: PumpCommandsCard (vertical ME/FBKW/PreIn sliders) + DfiCalibrationCard / PumpLiveDataCard (KPI tiles + RPM rolling chart + redesigned status bytes) / PumpIdentificationCard + DtcCard - Add PumpTopStripView: pump selector, model badge, CAN + K-Line chips - Move immobilizer unlock to MainWindow bottom snackbar (UnlockSnackbarView): auto-close on success after 3 s, persist on failure with manual Dismiss - Redesign StatusDisplayView to 2×8 rounded 28px tiles with bit index + tooltip - Add NullToVisibilityConverter; add SnackbarShell, PumpCard, and related styles - Delete obsolete views: UnlockProgressDialog, UnlockPanelView, PumpIdentificationPanelView, PumpLiveDataView, DfiManageView, DtcListView, PumpControlView - PumpPageViewModel: remove PumpSubPage enum, add RpmChart wired to Root.PumpRpm Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,262 +4,62 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels.Pages"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="780" d:DesignWidth="1100">
|
||||
d:DesignHeight="900" d:DesignWidth="1400">
|
||||
<!--
|
||||
Pump page — ECU diagnostics and control.
|
||||
DataContext = PumpPageViewModel.
|
||||
|
||||
Layout:
|
||||
- Banner row: K-Line session banner + "no pump selected" banner
|
||||
- Sub-nav (left): Identification / DTCs / LiveData / Adaptation / Unlock
|
||||
- Sub-page content (right): selected sub-section via hidden tabs
|
||||
Layout: top strip (row 0) + 3-column card body (row 1).
|
||||
Col 0 (1*, MinWidth=260): PumpCommandsCard (2*) + DfiCalibrationCard (1*)
|
||||
Col 1 (1.5*): PumpLiveDataCard (fills)
|
||||
Col 2 (1*, MinWidth=280): PumpIdentificationCard (Auto) + DtcCard (*)
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<!-- Sub-nav item: narrower than the main rail, same accent pattern -->
|
||||
<Style x:Key="SubNavItem" TargetType="ListBoxItem">
|
||||
<Setter Property="Height" Value="44"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ListBoxItem">
|
||||
<Border x:Name="Root" Background="Transparent">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border x:Name="Accent" Grid.Column="0" Background="Transparent"/>
|
||||
<ContentPresenter Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Margin="12,0,6,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Root" Property="Background" Value="#ECECEC"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter TargetName="Root" Property="Background" Value="#E4EEF7"/>
|
||||
<Setter TargetName="Accent" Property="Background" Value="#2196F3"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Opacity" Value="0.35"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SubNavText" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="Foreground" Value="#333"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid Margin="12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- banners -->
|
||||
<RowDefinition Height="*"/> <!-- body -->
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════════
|
||||
Banners: K-Line session + no pump selected
|
||||
══════════════════════════════════════════════════════════════ -->
|
||||
<StackPanel Grid.Row="0">
|
||||
<!-- ── Top status strip ─────────────────────────────────────────────── -->
|
||||
<uc:PumpTopStripView Grid.Row="0"/>
|
||||
|
||||
<!-- K-Line session banner (closed / failed) -->
|
||||
<Border Padding="10,6">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#FFF3CD"/>
|
||||
<Setter Property="BorderBrush" Value="#FFC107"/>
|
||||
<Setter Property="BorderThickness" Value="0,0,0,1"/>
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsKLineSessionOpen}" Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsKLineSessionFailed}" Value="True">
|
||||
<Setter Property="Background" Value="#FDECEA"/>
|
||||
<Setter Property="BorderBrush" Value="#D62828"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock FontSize="12" TextWrapping="Wrap">
|
||||
<Run Text="●" FontSize="14"/>
|
||||
<Run Text=" "/>
|
||||
<Run Text="{DynamicResource Pump.KLineClosed}"/>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<!-- No pump selected banner (BoolToVis has no Invert support, so use a DataTrigger style) -->
|
||||
<Border Background="#E3F2FD" BorderBrush="#2196F3" BorderThickness="0,0,0,1"
|
||||
Padding="10,6">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsPumpSelected}" Value="False">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Text="{DynamicResource Pump.NoPumpSelected}"
|
||||
FontSize="12" Foreground="#0D47A1"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════════
|
||||
Body: sub-nav + sub-page content
|
||||
══════════════════════════════════════════════════════════════ -->
|
||||
<!-- ── Body: 3-column card layout ───────────────────────────────────── -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="1*" MinWidth="260"/>
|
||||
<ColumnDefinition Width="1.5*"/>
|
||||
<ColumnDefinition Width="1*" MinWidth="280"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- ── Sub-nav rail ───────────────────────────────────────── -->
|
||||
<Border Grid.Column="0" Background="#F7F7F7"
|
||||
BorderBrush="#DDD" BorderThickness="0,0,1,0">
|
||||
<ListBox SelectedValuePath="Tag" BorderThickness="0"
|
||||
Background="Transparent"
|
||||
ItemContainerStyle="{StaticResource SubNavItem}"
|
||||
SelectedValue="{Binding SelectedSubPage, Mode=TwoWay}">
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Identification}">
|
||||
<TextBlock Text="{DynamicResource PumpSub.Identification}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Dtcs}"
|
||||
IsEnabled="{Binding IsPumpSelected}">
|
||||
<TextBlock Text="{DynamicResource PumpSub.Dtcs}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.LiveData}"
|
||||
IsEnabled="{Binding IsPumpSelected}">
|
||||
<TextBlock Text="{DynamicResource PumpSub.LiveData}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Adaptation}"
|
||||
IsEnabled="{Binding IsPumpSelected}">
|
||||
<TextBlock Text="{DynamicResource PumpSub.Adaptation}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Unlock}">
|
||||
<ListBoxItem.Style>
|
||||
<Style TargetType="ListBoxItem" BasedOn="{StaticResource SubNavItem}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsUnlockApplicable}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListBoxItem.Style>
|
||||
<TextBlock Text="{DynamicResource PumpSub.Unlock}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
</ListBox>
|
||||
</Border>
|
||||
<!-- Col 0: Commands (top 2*) + Idling Calibration (bottom 1*) -->
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- ── Sub-page content ───────────────────────────────────── -->
|
||||
<TabControl Grid.Column="1"
|
||||
Style="{StaticResource HiddenTabsTabControl}"
|
||||
SelectedIndex="{Binding SelectedSubPage, Converter={StaticResource EnumToInt}}">
|
||||
<uc:PumpCommandsCard Grid.Row="0" DataContext="{Binding PumpControl}"/>
|
||||
<uc:DfiCalibrationCard Grid.Row="1" DataContext="{Binding DfiViewModel}"/>
|
||||
</Grid>
|
||||
|
||||
<!-- 3a Identification -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<uc:PumpIdentificationPanelView
|
||||
DataContext="{Binding Identification}"/>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
<!-- Col 1: Live Data (full height) -->
|
||||
<uc:PumpLiveDataCard Grid.Column="1"/>
|
||||
|
||||
<!-- 3b DTCs -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<uc:DtcListView DataContext="{Binding DtcList}"/>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
<!-- Col 2: Identification (Auto) + DTCs (*) -->
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 3c Live Data — DataContext stays as PumpPageViewModel so
|
||||
the view can reach Root.PumpXxx and StatusDisplay1/2. -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<uc:PumpLiveDataView/>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- 3d Adaptation -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<Border Background="#FAFAFA" BorderBrush="#DDD"
|
||||
BorderThickness="1" CornerRadius="4"
|
||||
Padding="12" Margin="6">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource PumpSub.Adaptation}"
|
||||
FontSize="15" FontWeight="SemiBold"
|
||||
Foreground="#333" Margin="0,0,0,8"/>
|
||||
<uc:DfiManageView DataContext="{Binding DfiViewModel}"/>
|
||||
<Separator Margin="0,10"/>
|
||||
<uc:PumpControlView DataContext="{Binding PumpControl}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- 3e Unlock -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<Grid>
|
||||
<!-- "No active unlock" placeholder — visible when UnlockVm is null -->
|
||||
<Border Background="#F5F5F5" BorderBrush="#CCC"
|
||||
BorderThickness="1" CornerRadius="4"
|
||||
Padding="20" Margin="6"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding UnlockVm}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Text="{DynamicResource Pump.NoUnlockActive}"
|
||||
FontSize="13" Foreground="#666"/>
|
||||
</Border>
|
||||
|
||||
<!-- Active unlock panel — visible when UnlockVm is non-null.
|
||||
DataContext binds to UnlockVm so `{Binding}` inside the
|
||||
style evaluates to the VM instance (or null). -->
|
||||
<uc:UnlockPanelView DataContext="{Binding UnlockVm}">
|
||||
<uc:UnlockPanelView.Style>
|
||||
<Style TargetType="uc:UnlockPanelView">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</uc:UnlockPanelView.Style>
|
||||
</uc:UnlockPanelView>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
</TabControl>
|
||||
<uc:PumpIdentificationCard Grid.Row="0" DataContext="{Binding Identification}"/>
|
||||
<uc:DtcCard Grid.Row="1" DataContext="{Binding DtcList}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
Reference in New Issue
Block a user