Merge branch 'main' into XplorePlane

This commit is contained in:
zhengxuan.zhang
2026-03-11 16:01:53 +08:00
10 changed files with 565 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36811.4 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XplorePlane", "XplorePlane\XplorePlane.csproj", "{07978DB9-4B88-4F42-9054-73992742BD6A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{07978DB9-4B88-4F42-9054-73992742BD6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07978DB9-4B88-4F42-9054-73992742BD6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07978DB9-4B88-4F42-9054-73992742BD6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07978DB9-4B88-4F42-9054-73992742BD6A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DB6D69BA-49FD-432F-8069-2A8F64933CDE}
EndGlobalSection
EndGlobal
+7
View File
@@ -0,0 +1,7 @@
<Application x:Class="XplorePlane.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:XplorePlane">
<Application.Resources>
</Application.Resources>
</Application>
+37
View File
@@ -0,0 +1,37 @@
using System.Windows;
using XplorePlane.Views;
using XplorePlane.ViewModels;
using Prism.Ioc;
using Prism.DryIoc;
namespace XplorePlane
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// Initialize Prism with DryIoc
var bootstrapper = new AppBootstrapper();
bootstrapper.Run();
}
}
public class AppBootstrapper : PrismBootstrapper
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<MainWindow>();
containerRegistry.Register<MainViewModel>();
}
}
}
View File
+287
View File
@@ -0,0 +1,287 @@
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace XplorePlane.Models
{
// ── Navigation Tree Models ────────────────────────────────────────
public class NavGroupNode : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get => _name;
set { _name = value; OnPropertyChanged(); }
}
private ObservableCollection<object> _children;
public ObservableCollection<object> Children
{
get => _children;
set { _children = value; OnPropertyChanged(); }
}
public NavGroupNode(string name)
{
Name = name;
Children = new ObservableCollection<object>();
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public class NavLeafNode : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get => _name;
set { _name = value; OnPropertyChanged(); }
}
private string _iconColor;
public string IconColor
{
get => _iconColor;
set { _iconColor = value; OnPropertyChanged(); }
}
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set { _isSelected = value; OnPropertyChanged(); }
}
public NavLeafNode(string name, string IconColor = "#888888", bool IsSelected = false)
{
Name = name;
this.IconColor = IconColor;
this.IsSelected = IsSelected;
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// ── Inspection Callout Models ─────────────────────────────────────
public class InspectionCalloutVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _featureName;
public string FeatureName
{
get => _featureName;
set { _featureName = value; OnPropertyChanged(); }
}
private double _x;
public double X
{
get => _x;
set { _x = value; OnPropertyChanged(); }
}
private double _y;
public double Y
{
get => _y;
set { _y = value; OnPropertyChanged(); }
}
private ObservableCollection<CalloutRowVM> _rows;
public ObservableCollection<CalloutRowVM> Rows
{
get => _rows;
set { _rows = value; OnPropertyChanged(); }
}
public InspectionCalloutVM(string featureName, double x, double y, CalloutRowVM[] rows)
{
FeatureName = featureName;
X = x;
Y = y;
Rows = new ObservableCollection<CalloutRowVM>(rows);
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public class CalloutRowVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _label;
public string Label
{
get => _label;
set { _label = value; OnPropertyChanged(); }
}
private string _nominal;
public string Nominal
{
get => _nominal;
set { _nominal = value; OnPropertyChanged(); }
}
private string _measured;
public string Measured
{
get => _measured;
set { _measured = value; OnPropertyChanged(); }
}
private string _tolerance;
public string Tolerance
{
get => _tolerance;
set { _tolerance = value; OnPropertyChanged(); }
}
private string _deviation;
public string Deviation
{
get => _deviation;
set { _deviation = value; OnPropertyChanged(); }
}
private bool _isPass;
public bool IsPass
{
get => _isPass;
set { _isPass = value; OnPropertyChanged(); }
}
public CalloutRowVM(string label, string nominal, string measured, string tolerance, string deviation, bool isPass)
{
Label = label;
Nominal = nominal;
Measured = measured;
Tolerance = tolerance;
Deviation = deviation;
IsPass = isPass;
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// ── Feature Properties Model ──────────────────────────────────────
public class FeatureProperties : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get => _name;
set { _name = value; OnPropertyChanged(); }
}
private string _datumLabel;
public string DatumLabel
{
get => _datumLabel;
set { _datumLabel = value; OnPropertyChanged(); }
}
private double _x;
public double X
{
get => _x;
set { _x = value; OnPropertyChanged(); }
}
private double _y;
public double Y
{
get => _y;
set { _y = value; OnPropertyChanged(); }
}
private double _z;
public double Z
{
get => _z;
set { _z = value; OnPropertyChanged(); }
}
private double _nrX;
public double NrX
{
get => _nrX;
set { _nrX = value; OnPropertyChanged(); }
}
private double _nrY;
public double NrY
{
get => _nrY;
set { _nrY = value; OnPropertyChanged(); }
}
private double _nrZ;
public double NrZ
{
get => _nrZ;
set { _nrZ = value; OnPropertyChanged(); }
}
private double _height;
public double Height
{
get => _height;
set { _height = value; OnPropertyChanged(); }
}
private double _radius;
public double Radius
{
get => _radius;
set { _radius = value; OnPropertyChanged(); }
}
private double _diameter;
public double Diameter
{
get => _diameter;
set { _diameter = value; OnPropertyChanged(); }
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// ── RelayCommand Implementation ───────────────────────────────────
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
public void Execute(object parameter) => _execute(parameter);
}
}
+33
View File
@@ -0,0 +1,33 @@
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.ObjectModel;
namespace XplorePlane.ViewModels
{
public class MainViewModel : BindableBase
{
private string _licenseInfo = "µ±Ç°Ê±¼ä";
public ObservableCollection<object> NavigationTree { get; set; }
public DelegateCommand NavigateHomeCommand { get; set; }
public DelegateCommand NavigateInspectCommand { get; set; }
public DelegateCommand OpenFileCommand { get; set; }
public DelegateCommand ExportCommand { get; set; }
public DelegateCommand ClearCommand { get; set; }
public DelegateCommand EditPropertiesCommand { get; set; }
public MainViewModel()
{
NavigationTree = new ObservableCollection<object>();
NavigateHomeCommand = new DelegateCommand(() => { });
NavigateInspectCommand = new DelegateCommand(() => { });
OpenFileCommand = new DelegateCommand(() => { });
ExportCommand = new DelegateCommand(() => { });
ClearCommand = new DelegateCommand(() => { });
EditPropertiesCommand = new DelegateCommand(() => { });
}
}
}
@@ -0,0 +1,19 @@
using Prism.Mvvm;
namespace XplorePlane.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public MainWindowViewModel()
{
}
}
}
+138
View File
@@ -0,0 +1,138 @@
<Window x:Class="XplorePlane.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:XplorePlane.ViewModels"
xmlns:fluent="urn:fluent-ribbon"
mc:Ignorable="d"
Title="XplorePlane"
Height="768" Width="1080"
Background="#F5F5F5"
WindowStartupLocation="CenterScreen">
<Window.DataContext>
<vm:MainViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<!-- Row 0: Fluent Ribbon -->
<fluent:Ribbon Grid.Row="0" x:Name="Ribbon">
<fluent:RibbonTabItem Header="主页">
<fluent:RibbonGroupBox Header="导航">
<fluent:Button Header="主页" Command="{Binding NavigateHomeCommand}" LargeIcon="pack://application:,,,/Assets/Icons/home.png" Size="Large"/>
<fluent:Button Header="检测" Command="{Binding NavigateInspectCommand}" LargeIcon="pack://application:,,,/Assets/Icons/inspect.png" Size="Large"/>
</fluent:RibbonGroupBox>
<fluent:RibbonGroupBox Header="文件">
<fluent:Button Header="打开" Command="{Binding OpenFileCommand}" Icon="pack://application:,,,/Assets/Icons/open.png" Size="Middle"/>
<fluent:Button Header="导出" Command="{Binding ExportCommand}" Icon="pack://application:,,,/Assets/Icons/export.png" Size="Middle"/>
<fluent:Button Header="清空" Command="{Binding ClearCommand}" Icon="pack://application:,,,/Assets/Icons/clear.png" Size="Middle"/>
</fluent:RibbonGroupBox>
</fluent:RibbonTabItem>
<fluent:RibbonTabItem Header="编辑">
<fluent:RibbonGroupBox Header="操作">
<fluent:Button Header="修改属性" Command="{Binding EditPropertiesCommand}" Icon="pack://application:,,,/Assets/Icons/edit.png" Size="Middle"/>
</fluent:RibbonGroupBox>
</fluent:RibbonTabItem>
</fluent:Ribbon>
<!-- Row 1: Main Content -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300
" MinWidth="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="200" MinWidth="140"/>
</Grid.ColumnDefinitions>
<!-- Navigation Panel -->
<Grid Grid.Column="0" Background="#FFFFFF">
<Grid.RowDefinitions>
<RowDefinition Height="26"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,0,0,1">
<TextBlock Text="导航" Foreground="#333333" VerticalAlignment="Center" Margin="8,0" FontWeight="SemiBold"/>
</Border>
<TreeView Grid.Row="1" ItemsSource="{Binding NavigationTree}" Background="Transparent" BorderThickness="0" Foreground="#333333"/>
</Grid>
<!-- 3D Viewport -->
<Grid Grid.Column="1" Background="#E8E8E8">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="90"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="#FFFFFF" BorderBrush="#DDDDDD" BorderThickness="1" Margin="0,0,0,3" Grid.RowSpan="2">
<TextBlock Text="3D Viewport" Foreground="#666666" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16"/>
</Border>
</Grid>
<!-- Properties Panel -->
<Grid Grid.Column="2" Background="#FFFFFF">
<Grid.RowDefinitions>
<RowDefinition Height="26"/>
<RowDefinition Height="*"/>
<RowDefinition Height="28"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,0,0,1">
<TextBlock Text="属性" Foreground="#333333" VerticalAlignment="Center" Margin="8,0" FontWeight="SemiBold"/>
</Border>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<StackPanel Margin="4">
<Grid Margin="0,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="名称" Foreground="#666666"/>
<TextBlock Grid.Column="1" Text="{Binding SelectedFeature.Name}" Foreground="#333333"/>
</Grid>
<Grid Margin="0,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="X" Foreground="#666666"/>
<TextBlock Grid.Column="1" Text="{Binding SelectedFeature.X, StringFormat=F4}" Foreground="#333333"/>
</Grid>
</StackPanel>
</ScrollViewer>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="4,2">
<Button Content="修改属性" Command="{Binding EditPropertiesCommand}" Margin="0,0,4,0" Background="#0078D4" Foreground="White" BorderBrush="#0078D4"/>
</StackPanel>
</Grid>
</Grid>
<!-- Row 2: Status Bar -->
<Border Grid.Row="2" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,1,0,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding LicenseInfo}" Foreground="#666666" Margin="8,0" VerticalAlignment="Center"/>
<Border Grid.Column="2" Background="#0078D4" CornerRadius="2" Margin="4,3">
<TextBlock Text="{Binding ZoomLevel, StringFormat={}{0}%}" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="4,0"/>
</Border>
</Grid>
</Border>
</Grid>
</Window>
+15
View File
@@ -0,0 +1,15 @@
using System.Windows;
namespace XplorePlane.Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>