Forráskód Böngészése

refactor: UI 架构重构 - TabControl 改为 ContentControl + DataTemplate 模式

- MainWindow.axaml: 移除 TabControl,改用 ContentControl 绑定 CurrentView
- App.axaml: 添加 DataTemplate 定义,支持 ViewModel 到 View 的自动映射
- MainViewModel.cs: 简化 Tab 切换逻辑,移除项目档案偏移处理
- ViewB/ViewC/ViewD/ViewF: 添加 x:DataType 声明,DataGrid 改为 TableView
DESKTOP-74CLTRG\Leol 1 hónapja
szülő
commit
421fbcd822

+ 26 - 0
src/YZWater.Avalonia/App.axaml

@@ -1,5 +1,7 @@
 <Application xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:vm="using:YZWater.Core.ViewModels"
+             xmlns:views="using:YZWater.Avalonia.Views"
              x:Class="YZWater.Avalonia.App"
              RequestedThemeVariant="Light">
 
@@ -26,4 +28,28 @@
         </ResourceDictionary>
     </Application.Resources>
 
+    <Application.DataTemplates>
+        <DataTemplate DataType="vm:ProjectViewModel">
+            <views:ProjectView/>
+        </DataTemplate>
+        <DataTemplate DataType="vm:ViewAViewModel">
+            <views:ViewAView/>
+        </DataTemplate>
+        <DataTemplate DataType="vm:ViewBViewModel">
+            <views:ViewBView/>
+        </DataTemplate>
+        <DataTemplate DataType="vm:ViewCViewModel">
+            <views:ViewCView/>
+        </DataTemplate>
+        <DataTemplate DataType="vm:ViewDViewModel">
+            <views:ViewDView/>
+        </DataTemplate>
+        <DataTemplate DataType="vm:ViewEViewModel">
+            <views:ViewEView/>
+        </DataTemplate>
+        <DataTemplate DataType="vm:ViewFViewModel">
+            <views:ViewFView/>
+        </DataTemplate>
+    </Application.DataTemplates>
+
 </Application>

+ 53 - 75
src/YZWater.Avalonia/Views/MainWindow.axaml

@@ -147,86 +147,64 @@
 
         <!-- ═══ 主内容区域 ═══ -->
         <Panel>
-        <TabControl SelectedIndex="{Binding SelectedTabIndex}" Background="{DynamicResource AppBgBrush}">
-            <!-- 项目视图(当加载了项目档案时使用) -->
-            <TabItem Header="PROJECT" IsVisible="False" DataContext="{Binding ProjectView}">
-                <views:ProjectView/>
-            </TabItem>
-            <TabItem Header="PROCESS" IsVisible="False" DataContext="{Binding ViewA}">
-                <views:ViewAView/>
-            </TabItem>
-            <TabItem Header="PARAMS" IsVisible="False" DataContext="{Binding ViewB}">
-                <views:ViewBView/>
-            </TabItem>
-            <TabItem Header="FLOW" IsVisible="False" DataContext="{Binding ViewC}">
-                <views:ViewCView/>
-            </TabItem>
-            <TabItem Header="ALARM" IsVisible="False" DataContext="{Binding ViewD}">
-                <views:ViewDView/>
-            </TabItem>
-            <TabItem Header="ABOUT" IsVisible="False" DataContext="{Binding ViewE}">
-                <views:ViewEView/>
-            </TabItem>
-            <TabItem Header="AUDIT" IsVisible="False" DataContext="{Binding ViewF}">
-                <views:ViewFView/>
-            </TabItem>
-        </TabControl>
+            <!-- 视图内容(通过 CurrentView + DataTemplate 切换) -->
+            <ContentControl Content="{Binding CurrentView}"/>
 
-        <!-- ═══ 用户管理对话框 ═══ -->
-        <Border IsVisible="{Binding ShowUserDialog}" ZIndex="100" Background="#CC000000">
-            <Border Background="{DynamicResource CardBgBrush}" CornerRadius="12" Padding="24"
-                    MaxWidth="600" MaxHeight="500" VerticalAlignment="Center" HorizontalAlignment="Center"
-                    BorderBrush="{DynamicResource BorderBrush}" BorderThickness="1">
-                <DockPanel>
-                    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="12" Margin="0,0,0,16">
-                        <TextBlock Text="{Binding UserManageText}" FontSize="18" FontWeight="Bold"/>
-                        <Button Content="{Binding CloseText}" Command="{Binding ToggleUserDialogCommand}" HorizontalAlignment="Right" Classes="btn-danger"/>
-                    </StackPanel>
+            <!-- ═══ 用户管理对话框 ═══ -->
+            <Border IsVisible="{Binding ShowUserDialog}" ZIndex="100" Background="#CC000000">
+                <Border Background="{DynamicResource CardBgBrush}" CornerRadius="12" Padding="24"
+                        MaxWidth="600" MaxHeight="500" VerticalAlignment="Center" HorizontalAlignment="Center"
+                        BorderBrush="{DynamicResource BorderBrush}" BorderThickness="1">
+                    <DockPanel>
+                        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="12" Margin="0,0,0,16">
+                            <TextBlock Text="{Binding UserManageText}" FontSize="18" FontWeight="Bold"/>
+                            <Button Content="{Binding CloseText}" Command="{Binding ToggleUserDialogCommand}" HorizontalAlignment="Right" Classes="btn-danger"/>
+                        </StackPanel>
 
-                    <!-- 创建用户 -->
-                    <Border DockPanel.Dock="Top" Background="{DynamicResource CardBgBrush}" CornerRadius="8" Padding="12" Margin="0,0,0,12">
-                        <StackPanel Spacing="8">
-                            <TextBlock Text="{Binding CreateNewUserText}" FontWeight="Bold" FontSize="14"/>
-                            <StackPanel Orientation="Horizontal" Spacing="8">
-                                <TextBox Text="{Binding NewUserName}" PlaceholderText="{Binding UserNameLabel}" Width="120"/>
-                                <TextBox Text="{Binding NewUserPassword}" PlaceholderText="{Binding PasswordLabel}" PasswordChar="●" Width="120"/>
-                                <TextBox Text="{Binding NewUserDisplayName}" PlaceholderText="{Binding DisplayNameLabel}" Width="120"/>
-                                <ComboBox SelectedIndex="{Binding NewUserRole}" Width="100">
-                                    <ComboBoxItem Content="Viewer"/>
-                                    <ComboBoxItem Content="Operator"/>
-                                    <ComboBoxItem Content="Engineer"/>
-                                    <ComboBoxItem Content="Admin"/>
-                                </ComboBox>
-                                <Button Content="{Binding CreateText}" Command="{Binding CreateUserCommand}" Classes="btn-success"/>
+                        <!-- 创建用户 -->
+                        <Border DockPanel.Dock="Top" Background="{DynamicResource CardBgBrush}" CornerRadius="8" Padding="12" Margin="0,0,0,12">
+                            <StackPanel Spacing="8">
+                                <TextBlock Text="{Binding CreateNewUserText}" FontWeight="Bold" FontSize="14"/>
+                                <StackPanel Orientation="Horizontal" Spacing="8">
+                                    <TextBox Text="{Binding NewUserName}" PlaceholderText="{Binding UserNameLabel}" Width="120"/>
+                                    <TextBox Text="{Binding NewUserPassword}" PlaceholderText="{Binding PasswordLabel}" PasswordChar="●" Width="120"/>
+                                    <TextBox Text="{Binding NewUserDisplayName}" PlaceholderText="{Binding DisplayNameLabel}" Width="120"/>
+                                    <ComboBox SelectedIndex="{Binding NewUserRole}" Width="100">
+                                        <ComboBoxItem Content="Viewer"/>
+                                        <ComboBoxItem Content="Operator"/>
+                                        <ComboBoxItem Content="Engineer"/>
+                                        <ComboBoxItem Content="Admin"/>
+                                    </ComboBox>
+                                    <Button Content="{Binding CreateText}" Command="{Binding CreateUserCommand}" Classes="btn-success"/>
+                                </StackPanel>
+                                <TextBlock Text="{Binding UserManageMessage}" Foreground="Red" FontSize="12"/>
                             </StackPanel>
-                            <TextBlock Text="{Binding UserManageMessage}" Foreground="Red" FontSize="12"/>
-                        </StackPanel>
-                    </Border>
+                        </Border>
 
-                    <!-- 用户列表 -->
-                    <DataGrid ItemsSource="{Binding UserList}" AutoGenerateColumns="False" IsReadOnly="True"
-                              GridLinesVisibility="Horizontal" CanUserResizeColumns="True">
-                        <DataGrid.Columns>
-                            <DataGridTextColumn Header="User" Binding="{Binding UserName}" Width="100"/>
-                            <DataGridTextColumn Header="Name" Binding="{Binding DisplayName}" Width="120"/>
-                            <DataGridTextColumn Header="Role" Binding="{Binding Role}" Width="80"/>
-                            <DataGridTextColumn Header="Status" Binding="{Binding IsActive}" Width="60"/>
-                            <DataGridTextColumn Header="Last Login" Binding="{Binding LastLoginTime, StringFormat='yyyy-MM-dd HH:mm'}" Width="140"/>
-                            <DataGridTemplateColumn Header="Action" Width="80">
-                                <DataGridTemplateColumn.CellTemplate>
-                                    <DataTemplate>
-                                        <Button Content="{Binding IsActive, Converter={x:Static conv:BoolConverters.ToActiveText}}"
-                                                Command="{Binding $parent[DataGrid].((vm:MainViewModel)DataContext).ToggleUserActiveCommand}"
-                                                CommandParameter="{Binding}"
-                                                Classes="btn-toggle" Padding="6,2" FontSize="11"/>
-                                    </DataTemplate>
-                                </DataGridTemplateColumn.CellTemplate>
-                            </DataGridTemplateColumn>
-                        </DataGrid.Columns>
-                    </DataGrid>
-                </DockPanel>
+                        <!-- 用户列表 -->
+                        <DataGrid ItemsSource="{Binding UserList}" AutoGenerateColumns="False" IsReadOnly="True"
+                                  GridLinesVisibility="Horizontal" CanUserResizeColumns="True">
+                            <DataGrid.Columns>
+                                <DataGridTextColumn Header="User" Binding="{Binding UserName}" Width="100"/>
+                                <DataGridTextColumn Header="Name" Binding="{Binding DisplayName}" Width="120"/>
+                                <DataGridTextColumn Header="Role" Binding="{Binding Role}" Width="80"/>
+                                <DataGridTextColumn Header="Status" Binding="{Binding IsActive}" Width="60"/>
+                                <DataGridTextColumn Header="Last Login" Binding="{Binding LastLoginTime, StringFormat='yyyy-MM-dd HH:mm'}" Width="140"/>
+                                <DataGridTemplateColumn Header="Action" Width="80">
+                                    <DataGridTemplateColumn.CellTemplate>
+                                        <DataTemplate>
+                                            <Button Content="{Binding IsActive, Converter={x:Static conv:BoolConverters.ToActiveText}}"
+                                                    Command="{Binding $parent[DataGrid].((vm:MainViewModel)DataContext).ToggleUserActiveCommand}"
+                                                    CommandParameter="{Binding}"
+                                                    Classes="btn-toggle" Padding="6,2" FontSize="11"/>
+                                        </DataTemplate>
+                                    </DataGridTemplateColumn.CellTemplate>
+                                </DataGridTemplateColumn>
+                            </DataGrid.Columns>
+                        </DataGrid>
+                    </DockPanel>
+                </Border>
             </Border>
-        </Border>
         </Panel>
     </DockPanel>
 </Window>

+ 1 - 1
src/YZWater.Avalonia/Views/ViewBView.axaml

@@ -2,7 +2,7 @@
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:vm="using:YZWater.Core.ViewModels"
              x:Class="YZWater.Avalonia.Views.ViewBView"
-            >
+             x:DataType="vm:ViewBViewModel">
 
 
     <Border x:Name="RootBorder" Background="{DynamicResource AppBgBrush}">

+ 11 - 10
src/YZWater.Avalonia/Views/ViewCView.axaml

@@ -2,7 +2,8 @@
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:vm="using:YZWater.Core.ViewModels"
              xmlns:lvc="using:LiveChartsCore.SkiaSharpView.Avalonia"
-             x:Class="YZWater.Avalonia.Views.ViewCView">
+             x:Class="YZWater.Avalonia.Views.ViewCView"
+             x:DataType="vm:ViewCViewModel">
 
     <Border x:Name="RootBorder" Background="{DynamicResource AppBgBrush}">
         <Grid RowDefinitions="48,*,32">
@@ -96,15 +97,15 @@
                     <!-- 数据表格 -->
                     <Border Background="{DynamicResource SurfaceBgBrush}" CornerRadius="2"
                             BorderBrush="{DynamicResource BorderBrush}" BorderThickness="1" Padding="8" Margin="0,0,0,4">
-                        <DataGrid ItemsSource="{Binding FlowRecords}" AutoGenerateColumns="False" IsReadOnly="True" Height="150">
-                            <DataGrid.Columns>
-                                <DataGridTextColumn Header="Time" Binding="{Binding RecordTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
-                                <DataGridTextColumn Header="In (m³/h)" Binding="{Binding InflowRate, StringFormat='{}{0:F1}'}" Width="100"/>
-                                <DataGridTextColumn Header="Out (m³/h)" Binding="{Binding OutflowRate, StringFormat='{}{0:F1}'}" Width="100"/>
-                                <DataGridTextColumn Header="Total In (m³)" Binding="{Binding TotalInflow, StringFormat='{}{0:F1}'}" Width="120"/>
-                                <DataGridTextColumn Header="Total Out (m³)" Binding="{Binding TotalOutflow, StringFormat='{}{0:F1}'}" Width="120"/>
-                            </DataGrid.Columns>
-                        </DataGrid>
+                        <TableView ItemsSource="{Binding FlowRecords}" Height="150">
+                            <TableView.Columns>
+                                <TableViewColumn Header="Time" Binding="{Binding RecordTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
+                                <TableViewColumn Header="In (m³/h)" Binding="{Binding InflowRate, StringFormat='{}{0:F1}'}" Width="100"/>
+                                <TableViewColumn Header="Out (m³/h)" Binding="{Binding OutflowRate, StringFormat='{}{0:F1}'}" Width="100"/>
+                                <TableViewColumn Header="Total In (m³)" Binding="{Binding TotalInflow, StringFormat='{}{0:F1}'}" Width="120"/>
+                                <TableViewColumn Header="Total Out (m³)" Binding="{Binding TotalOutflow, StringFormat='{}{0:F1}'}" Width="120"/>
+                            </TableView.Columns>
+                        </TableView>
                     </Border>
                 </StackPanel>
             </ScrollViewer>

+ 12 - 14
src/YZWater.Avalonia/Views/ViewDView.axaml

@@ -2,7 +2,7 @@
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:vm="using:YZWater.Core.ViewModels"
              x:Class="YZWater.Avalonia.Views.ViewDView"
-            >
+             x:DataType="vm:ViewDViewModel">
 
 
     <Border x:Name="RootBorder" Background="{DynamicResource AppBgBrush}">
@@ -48,19 +48,17 @@
                 <!-- 报警列表 -->
                 <Border Grid.Row="1" Background="{DynamicResource SurfaceBgBrush}" CornerRadius="2"
                         BorderBrush="{DynamicResource BorderBrush}" BorderThickness="1" Padding="8" Margin="0,0,0,4">
-                    <DataGrid ItemsSource="{Binding AlarmRecords}" AutoGenerateColumns="False" IsReadOnly="True"
-                              SelectedItem="{Binding SelectedRecord}">
-                        <DataGrid.Columns>
-                            <DataGridTextColumn Header="TIME" Binding="{Binding AlarmTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
-                            <DataGridTextColumn Header="TYPE" Binding="{Binding AlarmType}" Width="100"/>
-                            <DataGridTextColumn Header="MESSAGE" Binding="{Binding AlarmMessage}" Width="250"/>
-                            <DataGridTextColumn Header="VALUE" Binding="{Binding AlarmValue, StringFormat='{}{0:F1}'}" Width="80"/>
-                            <DataGridTextColumn Header="LEVEL" Binding="{Binding AlarmLevel}" Width="60"/>
-                            <DataGridCheckBoxColumn Header="ACK" Binding="{Binding IsConfirmed}" Width="60"/>
-                            <DataGridTextColumn Header="ACK TIME" Binding="{Binding ConfirmedTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
-                            <DataGridTextColumn Header="ACK BY" Binding="{Binding ConfirmedBy}" Width="80"/>
-                        </DataGrid.Columns>
-                    </DataGrid>
+                    <TableView ItemsSource="{Binding AlarmRecords}">
+                        <TableView.Columns>
+                            <TableViewColumn Header="TIME" Binding="{Binding AlarmTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
+                            <TableViewColumn Header="TYPE" Binding="{Binding AlarmType}" Width="100"/>
+                            <TableViewColumn Header="MESSAGE" Binding="{Binding AlarmMessage}" Width="250"/>
+                            <TableViewColumn Header="VALUE" Binding="{Binding AlarmValue, StringFormat='{}{0:F1}'}" Width="80"/>
+                            <TableViewColumn Header="LEVEL" Binding="{Binding AlarmLevel}" Width="60"/>
+                            <TableViewColumn Header="ACK TIME" Binding="{Binding ConfirmedTime, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
+                            <TableViewColumn Header="ACK BY" Binding="{Binding ConfirmedBy}" Width="80"/>
+                        </TableView.Columns>
+                    </TableView>
                 </Border>
 
                 <!-- 报警详情 -->

+ 11 - 15
src/YZWater.Avalonia/Views/ViewFView.axaml

@@ -2,7 +2,7 @@
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:vm="using:YZWater.Core.ViewModels"
              x:Class="YZWater.Avalonia.Views.ViewFView"
-            >
+             x:DataType="vm:ViewFViewModel">
     <DockPanel Margin="16">
         <!-- 顶部工具栏 -->
         <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="12" Margin="0,0,0,12">
@@ -23,19 +23,15 @@
         </StackPanel>
 
         <!-- 审计日志表格 -->
-        <DataGrid ItemsSource="{Binding AuditLogs}"
-                  AutoGenerateColumns="False"
-                  IsReadOnly="True"
-                  GridLinesVisibility="Horizontal"
-                  CanUserResizeColumns="True">
-            <DataGrid.Columns>
-                <DataGridTextColumn Header="{Binding TimeHeaderText}" Binding="{Binding Timestamp, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
-                <DataGridTextColumn Header="{Binding UserHeaderText}" Binding="{Binding UserName}" Width="100"/>
-                <DataGridTextColumn Header="{Binding ActionHeaderText}" Binding="{Binding Action}" Width="100"/>
-                <DataGridTextColumn Header="{Binding DetailHeaderText}" Binding="{Binding Detail}" Width="*"/>
-                <DataGridTextColumn Header="{Binding TargetHeaderText}" Binding="{Binding Target}" Width="120"/>
-                <DataGridTextColumn Header="{Binding ResultHeaderText}" Binding="{Binding Result}" Width="80"/>
-            </DataGrid.Columns>
-        </DataGrid>
+        <TableView ItemsSource="{Binding AuditLogs}">
+            <TableView.Columns>
+                <TableViewColumn Header="{Binding TimeHeaderText}" Binding="{Binding Timestamp, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="160"/>
+                <TableViewColumn Header="{Binding UserHeaderText}" Binding="{Binding UserName}" Width="100"/>
+                <TableViewColumn Header="{Binding ActionHeaderText}" Binding="{Binding Action}" Width="100"/>
+                <TableViewColumn Header="{Binding DetailHeaderText}" Binding="{Binding Detail}" Width="*"/>
+                <TableViewColumn Header="{Binding TargetHeaderText}" Binding="{Binding Target}" Width="120"/>
+                <TableViewColumn Header="{Binding ResultHeaderText}" Binding="{Binding Result}" Width="80"/>
+            </TableView.Columns>
+        </TableView>
     </DockPanel>
 </UserControl>

+ 0 - 5
src/YZWater.Core/ViewModels/MainViewModel.cs

@@ -265,10 +265,6 @@ public partial class MainViewModel : ObservableObject, IDisposable
 
     private void SetActiveTab(int index)
     {
-        // 当加载了项目档案时,Tab 0 = ProjectView,原有 Tab 偏移 +1
-        var offset = HasProject ? 1 : 0;
-        var actualIndex = index + offset;
-        SelectedTabIndex = actualIndex;
         IsTabAActive = index == 0;
         IsTabBActive = index == 1;
         IsTabCActive = index == 2;
@@ -280,7 +276,6 @@ public partial class MainViewModel : ObservableObject, IDisposable
 
     [RelayCommand] private void ShowViewA()
     {
-        // 当加载了项目档案时,第一个 Tab 显示项目视图
         CurrentView = HasProject && _projectViewModel != null
             ? _projectViewModel
             : _viewAViewModel;