将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。
This commit is contained in:
+151
-28
@@ -1,44 +1,167 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<appSettings>
|
||||
<!-- Serilog 日志配置 -->
|
||||
<add key="Serilog:LogPath" value="logs" />
|
||||
<add key="Serilog:MinimumLevel" value="Information" />
|
||||
<!-- 语言配置 可选值: ZhCN, ZhTW, EnUS| Language Configuration -->
|
||||
<add key="Language" value="ZhCN" />
|
||||
<add key="UserManual" value="D:\HMQProject\XplorePlane_CT\Code\XplorePlane\XP.App\bin\Debug\net8.0-windows7.0\UserManual.pdf" />
|
||||
|
||||
<!-- Serilog日志配置 -->
|
||||
<add key="Serilog:LogPath" value="D:\XplorePlane\Logs" />
|
||||
<add key="Serilog:MinimumLevel" value="Debug" />
|
||||
<add key="Serilog:EnableConsole" value="true" />
|
||||
<add key="Serilog:RollingInterval" value="Day" />
|
||||
<add key="Serilog:FileSizeLimitMB" value="100" />
|
||||
<add key="Serilog:RetainedFileCountLimit" value="30" />
|
||||
<add key="Serilog:RetainedFileCountLimit" value="365" />
|
||||
|
||||
<!-- 射线源配置(key 格式: RaySource:xxx,与 ConfigLoader 一致) -->
|
||||
<add key="RaySource:PlcIpAddress" value="192.168.1.100" />
|
||||
<add key="RaySource:PlcPort" value="11160" />
|
||||
<!-- 数据库SQLite配置 -->
|
||||
<add key="Sqlite:DbFilePath" value="D:\XplorePlane\DataBase\XP.db" />
|
||||
<add key="Sqlite:ConnectionTimeout" value="10" />
|
||||
<add key="Sqlite:CreateIfNotExists" value="true" />
|
||||
<!-- 是否启用SQLite WAL模式(提升并发读写性能,默认true) -->
|
||||
<add key="Sqlite:EnableWalMode" value="true" />
|
||||
<!-- 是否开启SQL操作日志(记录所有执行的SQL语句,默认false) -->
|
||||
<add key="Sqlite:EnableSqlLogging" value="false" />
|
||||
|
||||
<!-- 射线源配置 -->
|
||||
<!-- 射线源类型 | Ray Source Type -->
|
||||
<!-- 可选值: Comet225 | Available values: Comet225 -->
|
||||
<add key="RaySource:SourceType" value="Comet225" />
|
||||
<add key="RaySource:SerialNumber" value="SN08602861" />
|
||||
<add key="RaySource:TotalLifeThreshold" value="10" />
|
||||
<!-- PVI通讯参数 | PVI Communication Parameters -->
|
||||
<add key="RaySource:PlcIpAddress" value="192.168.12.10" />
|
||||
<add key="RaySource:PlcPort" value="11159" />
|
||||
<add key="RaySource:PortNumber" value="11" />
|
||||
<add key="RaySource:StationNumber" value="1" />
|
||||
<add key="RaySource:CpuName" value="X20CP1584" />
|
||||
<add key="RaySource:ConnectionTimeout" value="5000" />
|
||||
<add key="RaySource:CpuName" value="cpu" />
|
||||
<add key="RaySource:ConnectionTimeout" value="30000" />
|
||||
<!-- 硬件参数范围 | Hardware Parameter Ranges -->
|
||||
<add key="RaySource:MinVoltage" value="20" />
|
||||
<add key="RaySource:MaxVoltage" value="225" />
|
||||
<add key="RaySource:MinCurrent" value="10" />
|
||||
<add key="RaySource:MaxCurrent" value="1000" />
|
||||
<add key="RaySource:WarmUpTimeout" value="300000" />
|
||||
<add key="RaySource:StartUpTimeout" value="180000" />
|
||||
<add key="RaySource:StatusPollingInterval" value="500" />
|
||||
<add key="RaySource:EnableAutoStatusMonitoring" value="true" />
|
||||
|
||||
<!-- SQLite 数据库配置 -->
|
||||
<add key="Sqlite:DbFilePath" value="Data\XP.db" />
|
||||
<add key="Sqlite:ConnectionTimeout" value="30" />
|
||||
<add key="Sqlite:CreateIfNotExists" value="true" />
|
||||
<add key="Sqlite:EnableWalMode" value="true" />
|
||||
<add key="Sqlite:EnableSqlLogging" value="false" />
|
||||
<add key="RaySource:MaxCurrent" value="1440" />
|
||||
<!-- 外部程序配置 | External Program Configuration -->
|
||||
<add key="RaySource:AdvanceExePath" value="C:\Program Files (x86)\Feinfocus\FXEControl_3.1.1.65\FXEControl.exe" />
|
||||
<!-- 操作超时配置 | Operation Timeout Configuration -->
|
||||
<add key="RaySource:RaySource:InitializationTimeout" value="30000" />
|
||||
<add key="RaySource:WarmUpTimeout" value="600000" />
|
||||
<add key="RaySource:StartUpTimeout" value="1800000" />
|
||||
<add key="RaySource:AutoCenterTimeout" value="1200000" />
|
||||
<add key="RaySource:FilamentAdjustTimeout" value="1200000" />
|
||||
<add key="RaySource:GeneralOperationTimeout" value="100000" />
|
||||
|
||||
<!-- 探测器配置 -->
|
||||
<add key="Detector.Type" value="Varex4343" />
|
||||
<add key="Detector.IPAddress" value="192.168.1.101" />
|
||||
<add key="Detector.Port" value="8080" />
|
||||
<!-- 探测器类型 | Detector Type -->
|
||||
<!-- 可选值: Varex, IRay, Hamamatsu | Available values: Varex, IRay, Hamamatsu -->
|
||||
<add key="Detector:Type" value="Varex" />
|
||||
<!-- 通用配置 | Common Configuration -->
|
||||
<add key="Detector:IP" value="192.168.1.200" />
|
||||
<add key="Detector:Port" value="5000" />
|
||||
<add key="Detector:SavePath" value="D:\XplorePlane\DetectorImages" />
|
||||
<add key="Detector:AutoSave" value="true" />
|
||||
<!-- Varex 探测器专属配置 | Varex Detector Specific Configuration -->
|
||||
<!-- Binning 模式: Bin1x1, Bin2x2, Bin4x4 | Binning mode: Bin1x1, Bin2x2, Bin4x4 -->
|
||||
<add key="Detector:Varex:BinningMode" value="Bin1x1" />
|
||||
<!-- 增益模式: Low, High | Gain mode: Low, High -->
|
||||
<add key="Detector:Varex:GainMode" value="High" />
|
||||
<!-- 曝光时间(毫秒)| Exposure time (milliseconds) -->
|
||||
<add key="Detector:Varex:ExposureTime" value="100" />
|
||||
<!-- ROI 区域 | ROI Region -->
|
||||
<add key="Detector:Varex:ROI_X" value="0" />
|
||||
<add key="Detector:Varex:ROI_Y" value="0" />
|
||||
<add key="Detector:Varex:ROI_Width" value="2880" />
|
||||
<add key="Detector:Varex:ROI_Height" value="2880" />
|
||||
<!-- iRay 探测器专属配置 | iRay Detector Specific Configuration -->
|
||||
<!-- 采集模式: Continuous, SingleFrame | Acquisition mode: Continuous, SingleFrame -->
|
||||
<add key="Detector:IRay:AcquisitionMode" value="Continuous" />
|
||||
<!-- 默认增益值 | Default gain value -->
|
||||
<add key="Detector:IRay:DefaultGain" value="1.0" />
|
||||
<!-- 校正配置 | Correction Configuration -->
|
||||
<add key="Detector:Correction:DarkFrameCount" value="10" />
|
||||
<add key="Detector:Correction:GainFrameCount" value="10" />
|
||||
<add key="Detector:Correction:SaveCorrectionData" value="true" />
|
||||
<!-- 操作超时配置 | Operation Timeout Configuration -->
|
||||
<add key="Detector:InitializationTimeout" value="30000" />
|
||||
<add key="Detector:AcquisitionTimeout" value="10000" />
|
||||
<add key="Detector:CorrectionTimeout" value="60000" />
|
||||
|
||||
<!-- PLC 配置 -->
|
||||
<add key="PLC.Type" value="B&R" />
|
||||
<add key="PLC.StationName" value="PLC_STATION" />
|
||||
<add key="PLC.ConnectionTimeout" value="5000" />
|
||||
<!-- Dump 配置 | Dump Configuration -->
|
||||
<add key="Dump:StoragePath" value="D:\XplorePlane\Dump" />
|
||||
<add key="Dump:EnableScheduledDump" value="false" />
|
||||
<add key="Dump:ScheduledIntervalMinutes" value="60" />
|
||||
<add key="Dump:MiniDumpSizeLimitMB" value="100" />
|
||||
<add key="Dump:RetentionDays" value="7" />
|
||||
|
||||
<!-- PLC 配置 | PLC Configuration -->
|
||||
<add key="Plc:IpAddress" value="192.168.0.1" />
|
||||
<add key="Plc:Port" value="102" />
|
||||
<add key="Plc:Rack" value="0" />
|
||||
<add key="Plc:Slot" value="1" />
|
||||
<!-- PlcType可选值: S200Smart, S300, S400, S1200, S1500 | PlcType Available values: S200Smart, S300, S400, S1200, S1500 -->
|
||||
<add key="Plc:PlcType" value="S1200" />
|
||||
<!-- 数据块配置 | Data Block Configuration -->
|
||||
<add key="Plc:ReadDbBlock" value="DB31" />
|
||||
<add key="Plc:WriteDbBlock" value="DB31" />
|
||||
<add key="Plc:ReadStartAddress" value="0" />
|
||||
<add key="Plc:ReadLength" value="200" />
|
||||
<!-- 批量读取周期(毫秒)| Bulk read interval (ms) -->
|
||||
<add key="Plc:BulkReadIntervalMs" value="250" />
|
||||
<!-- 超时配置 | Timeout Configuration -->
|
||||
<add key="Plc:ConnectTimeoutMs" value="3000" />
|
||||
<add key="Plc:ReadTimeoutMs" value="1000" />
|
||||
<add key="Plc:WriteTimeoutMs" value="1000" />
|
||||
<!-- 自动重连 | Auto Reconnection -->
|
||||
<add key="Plc:bReConnect" value="true" />
|
||||
|
||||
<!-- ==================== 运动控制配置 | Motion Control Configuration ==================== -->
|
||||
<!-- 直线轴配置(单位:mm)| Linear axis config (unit: mm) -->
|
||||
<add key="MotionControl:SourceZ:Min" value="-500" />
|
||||
<add key="MotionControl:SourceZ:Max" value="500" />
|
||||
<add key="MotionControl:SourceZ:Origin" value="0" />
|
||||
<add key="MotionControl:DetectorZ:Min" value="-600" />
|
||||
<add key="MotionControl:DetectorZ:Max" value="600" />
|
||||
<add key="MotionControl:DetectorZ:Origin" value="600" />
|
||||
<add key="MotionControl:StageX:Min" value="-150" />
|
||||
<add key="MotionControl:StageX:Max" value="150" />
|
||||
<add key="MotionControl:StageX:Origin" value="0" />
|
||||
<add key="MotionControl:StageY:Min" value="-150" />
|
||||
<add key="MotionControl:StageY:Max" value="150" />
|
||||
<add key="MotionControl:StageY:Origin" value="0" />
|
||||
<!-- 旋转轴配置(单位:度)| Rotary axis config (unit: degrees) -->
|
||||
<add key="MotionControl:DetectorSwing:Min" value="-45" />
|
||||
<add key="MotionControl:DetectorSwing:Max" value="45" />
|
||||
<add key="MotionControl:DetectorSwing:Origin" value="0" />
|
||||
<add key="MotionControl:DetectorSwing:Enabled" value="true" />
|
||||
<add key="MotionControl:StageRotation:Min" value="-360" />
|
||||
<add key="MotionControl:StageRotation:Max" value="360" />
|
||||
<add key="MotionControl:StageRotation:Origin" value="0" />
|
||||
<add key="MotionControl:StageRotation:Enabled" value="true" />
|
||||
<add key="MotionControl:FixtureRotation:Min" value="-90" />
|
||||
<add key="MotionControl:FixtureRotation:Max" value="90" />
|
||||
<add key="MotionControl:FixtureRotation:Origin" value="0" />
|
||||
<add key="MotionControl:FixtureRotation:Enabled" value="true" />
|
||||
<!-- 几何原点(mm)| Geometry origins (mm) -->
|
||||
<add key="MotionControl:Geometry:SourceZOrigin" value="0" />
|
||||
<add key="MotionControl:Geometry:DetectorZOrigin" value="600" />
|
||||
<add key="MotionControl:Geometry:StageRotationCenterZ" value="300" />
|
||||
<!-- 探测器摆动几何参数(mm)| Detector swing geometry parameters (mm) -->
|
||||
<!-- SwingPivotOffset: Pivot 相对于 DetectorZ 绝对坐标的 Z 方向偏移,正值表示 Pivot 在 DetectorZ_abs 上方 -->
|
||||
<add key="MotionControl:Geometry:SwingPivotOffset" value="80" />
|
||||
<!-- SwingRadius: Pivot 到探测器感光面中心的距离,为 0 时退化为无摆动模型 -->
|
||||
<add key="MotionControl:Geometry:SwingRadius" value="200" />
|
||||
<!-- 运行参数 | Runtime parameters -->
|
||||
<add key="MotionControl:PollingInterval" value="500" />
|
||||
<add key="MotionControl:DefaultVelocity" value="500" />
|
||||
</appSettings>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<!-- 允许捕获非托管异常(如 AccessViolationException)以便生成 Dump | Allow catching unmanaged exceptions (e.g. AccessViolationException) for dump generation -->
|
||||
<legacyCorruptedStateExceptionsPolicy enabled="true" />
|
||||
</runtime>
|
||||
</configuration>
|
||||
+89
-52
@@ -1,4 +1,5 @@
|
||||
using Prism.DryIoc;
|
||||
using DryIoc;
|
||||
using Prism.DryIoc;
|
||||
using Prism.Ioc;
|
||||
using Prism.Modularity;
|
||||
using Serilog;
|
||||
@@ -9,15 +10,25 @@ using System.Threading;
|
||||
using System.Windows;
|
||||
using Telerik.Windows.Controls;
|
||||
using XP.Camera;
|
||||
using XP.Common.Configs;
|
||||
using XP.Common.Database.Implementations;
|
||||
using XP.Common.Database.Interfaces;
|
||||
using XP.Common.Dump.Configs;
|
||||
using XP.Common.Dump.Implementations;
|
||||
using XP.Common.Dump.Interfaces;
|
||||
using XP.Common.Helpers;
|
||||
using XP.Common.Localization.Configs;
|
||||
using XP.Common.Localization.Extensions;
|
||||
using XP.Common.Localization.Implementations;
|
||||
using XP.Common.Localization.Interfaces;
|
||||
using XP.Common.Logging;
|
||||
using XP.Common.Logging.Implementations;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
using XP.Common.Module;
|
||||
using XP.Hardware.Detector.Module;
|
||||
using XP.Hardware.MotionControl.Module;
|
||||
using XP.Hardware.PLC;
|
||||
using XP.Hardware.RaySource.Module;
|
||||
using XP.Hardware.RaySource.Services;
|
||||
using XplorePlane.Services;
|
||||
using XplorePlane.Services.AppState;
|
||||
@@ -38,13 +49,10 @@ namespace XplorePlane
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
// 设置 Telerik Windows11 主题,缩小 Ribbon 整体尺寸
|
||||
StyleManager.ApplicationTheme = new Windows11Theme();
|
||||
//Windows11Palette.Palette.FontSize = 11;
|
||||
//Windows11Palette.Palette.FontSizeS = 10;
|
||||
//Windows11Palette.Palette.FontSizeL = 13;
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
// 设置 Telerik Windows11 主题,缩小 Ribbon 整体尺寸
|
||||
StyleManager.ApplicationTheme = new Windows11Theme();
|
||||
|
||||
// 强制使用中文 UI,确保 ImageProcessing 库显示中文
|
||||
var zhCN = new CultureInfo("zh-CN");
|
||||
@@ -56,8 +64,8 @@ namespace XplorePlane
|
||||
// 配置 Serilog 日志系统
|
||||
ConfigureLogging();
|
||||
|
||||
// 捕获未处理的异常
|
||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||
// 捕获未处理的异常
|
||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||
DispatcherUnhandledException += OnDispatcherUnhandledException;
|
||||
|
||||
try
|
||||
@@ -92,14 +100,12 @@ namespace XplorePlane
|
||||
|
||||
private void ConfigureLogging()
|
||||
{
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.Debug()
|
||||
.WriteTo.Console()
|
||||
.WriteTo.File("logs/xploreplane-.log",
|
||||
rollingInterval: RollingInterval.Day,
|
||||
retainedFileCountLimit: 30)
|
||||
.CreateLogger();
|
||||
// 加载Serilog配置 | Load Serilog configuration
|
||||
SerilogConfig serilogConfig = ConfigLoader.LoadSerilogConfig();
|
||||
// 初始化Serilog(全局唯一)| Initialize Serilog (global singleton)
|
||||
SerilogInitializer.Initialize(serilogConfig);
|
||||
|
||||
// 记录应用启动日志 | Log application startup
|
||||
Log.Information("========================================");
|
||||
Log.Information("XplorePlane 应用程序启动");
|
||||
Log.Information("========================================");
|
||||
@@ -159,7 +165,23 @@ namespace XplorePlane
|
||||
Log.Error(ex, "相机服务资源释放失败");
|
||||
}
|
||||
|
||||
Log.CloseAndFlush();
|
||||
// 释放SQLite数据库资源 | Release SQLite database resources
|
||||
try
|
||||
{
|
||||
var bootstrapper = AppBootstrapper.Instance;
|
||||
if (bootstrapper != null)
|
||||
{
|
||||
var dbContext = bootstrapper.Container.Resolve<IDbContext>(); // 从Prism容器获取IDbContext实例(单例)| Get IDbContext instance from Prism container (singleton)
|
||||
dbContext?.Dispose();
|
||||
Log.Information("数据库资源已成功释放 | Database resources released successfully");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "数据库资源释放失败,忽略该错误继续退出 | Database resource release failed, ignoring error and continuing exit");
|
||||
}
|
||||
|
||||
Log.CloseAndFlush();
|
||||
base.OnExit(e);
|
||||
}
|
||||
|
||||
@@ -168,7 +190,7 @@ namespace XplorePlane
|
||||
/// </summary>
|
||||
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
var exception = e.ExceptionObject as Exception;
|
||||
var exception = e.ExceptionObject as Exception;
|
||||
Log.Fatal(exception, "应用程序发生未处理的异常");
|
||||
|
||||
MessageBox.Show(
|
||||
@@ -207,21 +229,45 @@ namespace XplorePlane
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
private bool _modulesInitialized = false;
|
||||
|
||||
protected override Window CreateShell()
|
||||
{
|
||||
// 提前初始化模块,确保硬件服务在 MainWindow XAML 解析前已注册
|
||||
// 默认 Prism 顺序是 CreateShell → InitializeModules,
|
||||
// 但 MainWindow 中嵌入的硬件控件会在 XAML 解析时触发 ViewModelLocator,
|
||||
// 此时模块尚未加载,导致依赖解析失败
|
||||
if (!_modulesInitialized)
|
||||
{
|
||||
base.InitializeModules();
|
||||
_modulesInitialized = true;
|
||||
}
|
||||
|
||||
return Container.Resolve<MainWindow>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模块已在 CreateShell 中提前初始化,此处跳过避免重复加载
|
||||
/// </summary>
|
||||
protected override void InitializeModules()
|
||||
{
|
||||
if (!_modulesInitialized)
|
||||
{
|
||||
base.InitializeModules();
|
||||
_modulesInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
// 注册 Serilog 的 ILogger 实例
|
||||
containerRegistry.RegisterInstance<ILogger>(Log.Logger);
|
||||
|
||||
// 注册 XP.Common.ILoggerService 适配器
|
||||
containerRegistry.RegisterSingleton<XP.Common.Logging.Interfaces.ILoggerService, Services.LoggerServiceAdapter>();
|
||||
// 注册 XP.Common.ILoggerService 适配器
|
||||
containerRegistry.RegisterSingleton<ILoggerService, SerilogLoggerService>();
|
||||
|
||||
// 注册视图和视图模型
|
||||
containerRegistry.RegisterForNavigation<MainWindow>();
|
||||
// 注册视图和视图模型
|
||||
containerRegistry.RegisterForNavigation<MainWindow>();
|
||||
containerRegistry.RegisterForNavigation<MainWindowB>();
|
||||
containerRegistry.Register<MainViewModel>();
|
||||
containerRegistry.RegisterSingleton<NavigationPropertyPanelViewModel>();
|
||||
@@ -253,12 +299,14 @@ namespace XplorePlane
|
||||
containerRegistry.RegisterInstance(sqliteConfig);
|
||||
containerRegistry.RegisterSingleton<IDbContext, SqliteContext>();
|
||||
|
||||
// 注册硬件库的 ViewModel(供 ViewModelLocator 自动装配)
|
||||
//containerRegistry.Register<XP.Hardware.RaySource.ViewModels.RaySourceOperateViewModel>();
|
||||
// 手动注册射线源模块的所有服务(确保 DryIoc 容器中可用,避免模块加载顺序问题)
|
||||
var raySourceConfig = XP.Hardware.RaySource.Config.ConfigLoader.LoadConfig();
|
||||
containerRegistry.RegisterInstance(raySourceConfig);
|
||||
containerRegistry.RegisterSingleton<XP.Hardware.RaySource.Abstractions.IRaySourceFactory, XP.Hardware.RaySource.Factories.RaySourceFactory>();
|
||||
containerRegistry.RegisterSingleton<IRaySourceService, XP.Hardware.RaySource.Services.RaySourceService>();
|
||||
containerRegistry.RegisterSingleton<XP.Hardware.RaySource.Services.IFilamentLifetimeService, XP.Hardware.RaySource.Services.FilamentLifetimeService>();
|
||||
//var raySourceConfig = XP.Hardware.RaySource.Config.ConfigLoader.LoadConfig();
|
||||
//containerRegistry.RegisterInstance(raySourceConfig);
|
||||
//containerRegistry.RegisterSingleton<XP.Hardware.RaySource.Abstractions.IRaySourceFactory, XP.Hardware.RaySource.Factories.RaySourceFactory>();
|
||||
//containerRegistry.RegisterSingleton<IRaySourceService, XP.Hardware.RaySource.Services.RaySourceService>();
|
||||
//containerRegistry.RegisterSingleton<XP.Hardware.RaySource.Services.IFilamentLifetimeService, XP.Hardware.RaySource.Services.FilamentLifetimeService>();
|
||||
|
||||
// 手动注册通用模块的服务(本地化、Dump)
|
||||
containerRegistry.RegisterSingleton<ILocalizationConfig, LocalizationConfig>();
|
||||
@@ -291,31 +339,20 @@ namespace XplorePlane
|
||||
|
||||
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
|
||||
{
|
||||
// 所有模块服务已在 RegisterTypes 中手动注册
|
||||
// CommonModule: ILocalizationService, IDumpService
|
||||
// RaySourceModule: IRaySourceService, IRaySourceFactory, IFilamentLifetimeService
|
||||
// 所有模块服务已在 RegisterTypes 中手动注册
|
||||
// CommonModule: ILocalizationService, IDumpService
|
||||
// RaySourceModule: IRaySourceService, IRaySourceFactory, IFilamentLifetimeService
|
||||
|
||||
// 注册通用模块(必须最先加载)| Register common module (must be loaded first)
|
||||
moduleCatalog.AddModule<CommonModule>();
|
||||
|
||||
// 注册其他模块 | Register other modules
|
||||
moduleCatalog.AddModule<PLCModule>();
|
||||
moduleCatalog.AddModule<DetectorModule>();
|
||||
moduleCatalog.AddModule<RaySourceModule>();
|
||||
moduleCatalog.AddModule<MotionControlModule>();
|
||||
|
||||
base.ConfigureModuleCatalog(moduleCatalog);
|
||||
}
|
||||
|
||||
protected override void InitializeModules()
|
||||
{
|
||||
base.InitializeModules();
|
||||
|
||||
// 手动初始化本地化扩展(原由 CommonModule.OnInitialized 完成)
|
||||
// 必须在 CreateShell 之前执行,XAML 中的 {loc:Localization} 标记扩展依赖它
|
||||
var locService = Container.Resolve<ILocalizationService>();
|
||||
LocalizationExtension.Initialize(locService);
|
||||
|
||||
// 启动 Dump 服务
|
||||
try
|
||||
{
|
||||
var dumpService = Container.Resolve<IDumpService>();
|
||||
dumpService.Start();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Dump 服务启动失败,跳过");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,21 @@
|
||||
using Prism.Commands;
|
||||
using Prism.Ioc;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
using XP.Common.PdfViewer.Interfaces;
|
||||
using XP.Hardware.MotionControl.Abstractions;
|
||||
|
||||
namespace XplorePlane.ViewModels
|
||||
{
|
||||
public class MainViewModel : BindableBase
|
||||
{
|
||||
private readonly ILoggerService _logger;
|
||||
private readonly IContainerProvider _containerProvider;
|
||||
private string _licenseInfo = "当前时间";
|
||||
|
||||
public string LicenseInfo
|
||||
@@ -18,60 +26,300 @@ namespace XplorePlane.ViewModels
|
||||
|
||||
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 DelegateCommand OpenImageProcessingCommand { get; set; }
|
||||
public DelegateCommand OpenPipelineEditorCommand { get; set; }
|
||||
public DelegateCommand OpenCncEditorCommand { get; set; }
|
||||
public DelegateCommand OpenMatrixEditorCommand { get; set; }
|
||||
|
||||
public MainViewModel(ILoggerService logger)
|
||||
// 窗口打开命令
|
||||
public DelegateCommand OpenImageProcessingCommand { get; }
|
||||
public DelegateCommand OpenPipelineEditorCommand { get; }
|
||||
public DelegateCommand OpenCncEditorCommand { get; }
|
||||
public DelegateCommand OpenMatrixEditorCommand { get; }
|
||||
public DelegateCommand OpenToolboxCommand { get; }
|
||||
public DelegateCommand OpenLibraryVersionsCommand { get; }
|
||||
public DelegateCommand OpenUserManualCommand { get; }
|
||||
public DelegateCommand OpenCameraSettingsCommand { get; }
|
||||
|
||||
// 硬件命令
|
||||
public DelegateCommand AxisResetCommand { get; }
|
||||
public DelegateCommand OpenDetectorConfigCommand { get; }
|
||||
public DelegateCommand OpenMotionDebugCommand { get; }
|
||||
public DelegateCommand OpenPlcAddrConfigCommand { get; }
|
||||
public DelegateCommand OpenRaySourceConfigCommand { get; }
|
||||
public DelegateCommand WarmUpCommand { get; }
|
||||
|
||||
// 设置命令
|
||||
public DelegateCommand OpenLanguageSwitcherCommand { get; }
|
||||
public DelegateCommand OpenRealTimeLogViewerCommand { get; }
|
||||
|
||||
// 窗口引用(单例窗口防止重复打开)
|
||||
private Window _motionDebugWindow;
|
||||
private Window _detectorConfigWindow;
|
||||
private Window _plcAddrConfigWindow;
|
||||
private Window _realTimeLogViewerWindow;
|
||||
private Window _toolboxWindow;
|
||||
private Window _raySourceConfigWindow;
|
||||
|
||||
public MainViewModel(ILoggerService logger, IContainerProvider containerProvider)
|
||||
{
|
||||
_logger = logger?.ForModule<MainViewModel>() ?? throw new System.ArgumentNullException(nameof(logger));
|
||||
_logger = logger?.ForModule<MainViewModel>() ?? throw new ArgumentNullException(nameof(logger));
|
||||
_containerProvider = containerProvider ?? throw new ArgumentNullException(nameof(containerProvider));
|
||||
|
||||
NavigationTree = new ObservableCollection<object>();
|
||||
|
||||
// 导航命令
|
||||
NavigateHomeCommand = new DelegateCommand(OnNavigateHome);
|
||||
NavigateInspectCommand = new DelegateCommand(OnNavigateInspect);
|
||||
OpenFileCommand = new DelegateCommand(OnOpenFile);
|
||||
ExportCommand = new DelegateCommand(OnExport);
|
||||
ClearCommand = new DelegateCommand(OnClear);
|
||||
EditPropertiesCommand = new DelegateCommand(OnEditProperties);
|
||||
OpenImageProcessingCommand = new DelegateCommand(() =>
|
||||
{
|
||||
var window = new Views.ImageProcessingWindow();
|
||||
window.Show();
|
||||
_logger.Info("图像处理窗口已打开");
|
||||
});
|
||||
|
||||
OpenPipelineEditorCommand = new DelegateCommand(() =>
|
||||
{
|
||||
var window = new Views.PipelineEditorWindow();
|
||||
window.Show();
|
||||
_logger.Info("流水线编辑器窗口已打开");
|
||||
});
|
||||
// 窗口打开命令
|
||||
OpenImageProcessingCommand = new DelegateCommand(() => ShowWindow(new Views.ImageProcessingWindow(), "图像处理"));
|
||||
OpenPipelineEditorCommand = new DelegateCommand(() => ShowWindow(new Views.PipelineEditorWindow(), "流水线编辑器"));
|
||||
OpenCncEditorCommand = new DelegateCommand(() => ShowWindow(new Views.Cnc.CncEditorWindow(), "CNC 编辑器"));
|
||||
OpenMatrixEditorCommand = new DelegateCommand(() => ShowWindow(new Views.Cnc.MatrixEditorWindow(), "矩阵编排"));
|
||||
OpenToolboxCommand = new DelegateCommand(ExecuteOpenToolbox);
|
||||
OpenLibraryVersionsCommand = new DelegateCommand(() => ShowWindow(new Views.LibraryVersionsWindow(), "关于"));
|
||||
OpenUserManualCommand = new DelegateCommand(ExecuteOpenUserManual);
|
||||
OpenCameraSettingsCommand = new DelegateCommand(ExecuteOpenCameraSettings);
|
||||
|
||||
OpenCncEditorCommand = new DelegateCommand(() =>
|
||||
{
|
||||
var window = new Views.Cnc.CncEditorWindow();
|
||||
window.Show();
|
||||
_logger.Info("CNC 编辑器窗口已打开");
|
||||
});
|
||||
// 硬件命令
|
||||
AxisResetCommand = new DelegateCommand(ExecuteAxisReset);
|
||||
OpenDetectorConfigCommand = new DelegateCommand(ExecuteOpenDetectorConfig);
|
||||
OpenMotionDebugCommand = new DelegateCommand(ExecuteOpenMotionDebug);
|
||||
OpenPlcAddrConfigCommand = new DelegateCommand(ExecuteOpenPlcAddrConfig);
|
||||
OpenRaySourceConfigCommand = new DelegateCommand(ExecuteOpenRaySourceConfig);
|
||||
WarmUpCommand = new DelegateCommand(ExecuteWarmUp);
|
||||
|
||||
OpenMatrixEditorCommand = new DelegateCommand(() =>
|
||||
{
|
||||
var window = new Views.Cnc.MatrixEditorWindow();
|
||||
window.Show();
|
||||
_logger.Info("矩阵编排窗口已打开");
|
||||
});
|
||||
// 设置命令
|
||||
OpenLanguageSwitcherCommand = new DelegateCommand(ExecuteOpenLanguageSwitcher);
|
||||
OpenRealTimeLogViewerCommand = new DelegateCommand(ExecuteOpenRealTimeLogViewer);
|
||||
|
||||
_logger.Info("MainViewModel 已初始化");
|
||||
}
|
||||
|
||||
#region 通用窗口辅助方法
|
||||
|
||||
/// <summary>
|
||||
/// 显示一个新窗口(非模态)
|
||||
/// </summary>
|
||||
private void ShowWindow(Window window, string name)
|
||||
{
|
||||
window.Owner = Application.Current.MainWindow;
|
||||
window.Show();
|
||||
_logger.Info("{Name} 窗口已打开", name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示或激活单例窗口(非模态,防止重复打开)
|
||||
/// </summary>
|
||||
private void ShowOrActivate(Window currentWindow, Action<Window> setWindow, Func<Window> factory, string name)
|
||||
{
|
||||
if (currentWindow != null && currentWindow.IsLoaded)
|
||||
{
|
||||
currentWindow.Activate();
|
||||
return;
|
||||
}
|
||||
|
||||
var window = factory();
|
||||
window.Owner = Application.Current.MainWindow;
|
||||
window.ShowInTaskbar = true;
|
||||
window.Closed += (s, e) => setWindow(null);
|
||||
window.Show();
|
||||
setWindow(window);
|
||||
_logger.Info("{Name} 窗口已打开", name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 窗口打开命令实现
|
||||
|
||||
private void ExecuteOpenToolbox()
|
||||
{
|
||||
ShowOrActivate(_toolboxWindow, w => _toolboxWindow = w, () => new Views.OperatorToolboxWindow(), "算子工具箱");
|
||||
}
|
||||
|
||||
private void ExecuteOpenUserManual()
|
||||
{
|
||||
try
|
||||
{
|
||||
var manualPath = ConfigurationManager.AppSettings["UserManual"];
|
||||
if (string.IsNullOrEmpty(manualPath))
|
||||
{
|
||||
_logger.Warn("未配置用户手册路径");
|
||||
MessageBox.Show("未配置用户手册路径,请检查 App.config 中的 UserManual 配置项。",
|
||||
"提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!File.Exists(manualPath))
|
||||
{
|
||||
_logger.Warn("用户手册文件不存在:{Path}", manualPath);
|
||||
MessageBox.Show($"用户手册文件不存在:\n{manualPath}",
|
||||
"提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var pdfViewerService = _containerProvider.Resolve<IPdfViewerService>();
|
||||
var stream = File.OpenRead(manualPath);
|
||||
var fileName = Path.GetFileName(manualPath);
|
||||
pdfViewerService.OpenViewer(stream, fileName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "打开用户手册失败");
|
||||
MessageBox.Show($"打开用户手册失败:{ex.Message}",
|
||||
"错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteOpenCameraSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
var vm = _containerProvider.Resolve<NavigationPropertyPanelViewModel>();
|
||||
if (!vm.IsCameraConnected)
|
||||
{
|
||||
MessageBox.Show("请先连接相机", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var window = new Views.CameraSettingsWindow(vm) { Owner = Application.Current.MainWindow };
|
||||
window.Show();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "打开相机设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 硬件命令实现
|
||||
|
||||
private void ExecuteAxisReset()
|
||||
{
|
||||
var result = MessageBox.Show("确认执行轴复位操作?", "轴复位",
|
||||
MessageBoxButton.OKCancel, MessageBoxImage.Question);
|
||||
if (result != MessageBoxResult.OK) return;
|
||||
|
||||
try
|
||||
{
|
||||
var motionSystem = _containerProvider.Resolve<IMotionSystem>();
|
||||
var resetResult = motionSystem.AxisReset.Reset();
|
||||
if (!resetResult.Success)
|
||||
{
|
||||
MessageBox.Show($"轴复位失败:{resetResult.ErrorMessage}", "错误",
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "轴复位异常");
|
||||
MessageBox.Show($"轴复位异常:{ex.Message}", "错误",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteOpenDetectorConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
ShowOrActivate(_detectorConfigWindow, w => _detectorConfigWindow = w,
|
||||
() => new XP.Hardware.Detector.Views.DetectorConfigWindow(), "探测器配置");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "打开探测器配置窗口失败");
|
||||
MessageBox.Show($"打开探测器配置窗口失败:\n{ex.InnerException?.Message ?? ex.Message}",
|
||||
"错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteOpenMotionDebug()
|
||||
{
|
||||
ShowOrActivate(_motionDebugWindow, w => _motionDebugWindow = w,
|
||||
() => new XP.Hardware.MotionControl.Views.MotionDebugWindow(), "运动调试");
|
||||
}
|
||||
|
||||
private void ExecuteOpenPlcAddrConfig()
|
||||
{
|
||||
ShowOrActivate(_plcAddrConfigWindow, w => _plcAddrConfigWindow = w,
|
||||
() => _containerProvider.Resolve<XP.Hardware.PLC.Views.PlcAddrConfigEditorWindow>(), "PLC 地址配置");
|
||||
}
|
||||
|
||||
private void ExecuteOpenRaySourceConfig()
|
||||
{
|
||||
ShowOrActivate(_raySourceConfigWindow, w => _raySourceConfigWindow = w,
|
||||
() => new XP.Hardware.RaySource.Views.RaySourceConfigWindow(), "射线源配置");
|
||||
}
|
||||
|
||||
private void ExecuteWarmUp()
|
||||
{
|
||||
var messageBoxResult = MessageBox.Show("确认执行射线源暖机操作?", "暖机",
|
||||
MessageBoxButton.OKCancel, MessageBoxImage.Question);
|
||||
if (messageBoxResult != MessageBoxResult.OK) return;
|
||||
|
||||
try
|
||||
{
|
||||
var raySourceService = _containerProvider.Resolve<XP.Hardware.RaySource.Services.IRaySourceService>();
|
||||
var result = raySourceService.WarmUp();
|
||||
if (!result.Success)
|
||||
{
|
||||
MessageBox.Show($"暖机失败:{result.ErrorMessage}", "错误",
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("暖机命令已发送");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "暖机异常");
|
||||
MessageBox.Show($"暖机异常:{ex.Message}", "错误",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 设置命令实现
|
||||
|
||||
private void ExecuteOpenLanguageSwitcher()
|
||||
{
|
||||
try
|
||||
{
|
||||
var viewModel = _containerProvider.Resolve<XP.Common.Localization.ViewModels.LanguageSwitcherViewModel>();
|
||||
var window = new XP.Common.Localization.Views.LanguageSwitcherWindow(viewModel)
|
||||
{
|
||||
Owner = Application.Current.MainWindow,
|
||||
ShowInTaskbar = true
|
||||
};
|
||||
window.ShowDialog();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "打开语言设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteOpenRealTimeLogViewer()
|
||||
{
|
||||
ShowOrActivate(_realTimeLogViewerWindow, w => _realTimeLogViewerWindow = w,
|
||||
() => new XP.Common.GeneralForm.Views.RealTimeLogViewer(), "实时日志");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 导航命令实现
|
||||
|
||||
private void OnNavigateHome()
|
||||
{
|
||||
_logger.Info("导航到主页");
|
||||
@@ -107,5 +355,7 @@ namespace XplorePlane.ViewModels
|
||||
_logger.Info("编辑属性");
|
||||
LicenseInfo = "编辑属性";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
using XP.Hardware.Detector.Abstractions;
|
||||
using XP.Hardware.Detector.Abstractions.Events;
|
||||
|
||||
namespace XplorePlane.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// 实时图像 ViewModel,订阅探测器采集事件并显示图像
|
||||
/// </summary>
|
||||
public class ViewportPanelViewModel : BindableBase
|
||||
{
|
||||
private readonly ILoggerService _logger;
|
||||
private int _isProcessingFrame;
|
||||
|
||||
private ImageSource _imageSource;
|
||||
public ImageSource ImageSource
|
||||
{
|
||||
get => _imageSource;
|
||||
set => SetProperty(ref _imageSource, value);
|
||||
}
|
||||
|
||||
private string _imageInfo = "等待图像...";
|
||||
public string ImageInfo
|
||||
{
|
||||
get => _imageInfo;
|
||||
set => SetProperty(ref _imageInfo, value);
|
||||
}
|
||||
|
||||
public ViewportPanelViewModel(IEventAggregator eventAggregator, ILoggerService logger)
|
||||
{
|
||||
_logger = logger?.ForModule<ViewportPanelViewModel>();
|
||||
|
||||
eventAggregator.GetEvent<ImageCapturedEvent>()
|
||||
.Subscribe(OnImageCaptured, ThreadOption.BackgroundThread);
|
||||
}
|
||||
|
||||
private void OnImageCaptured(ImageCapturedEventArgs args)
|
||||
{
|
||||
if (args?.ImageData == null || args.Width == 0 || args.Height == 0) return;
|
||||
|
||||
// 帧节流:上一帧未消费完则跳过
|
||||
if (Interlocked.CompareExchange(ref _isProcessingFrame, 1, 0) != 0) return;
|
||||
|
||||
try
|
||||
{
|
||||
var bitmap = ConvertToBitmapSource(args.ImageData, (int)args.Width, (int)args.Height);
|
||||
bitmap.Freeze();
|
||||
|
||||
var info = $"{args.Width}×{args.Height} 帧#{args.FrameNumber} {args.CaptureTime:HH:mm:ss.fff}";
|
||||
|
||||
Application.Current?.Dispatcher?.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
ImageSource = bitmap;
|
||||
ImageInfo = info;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Exchange(ref _isProcessingFrame, 0);
|
||||
}
|
||||
}));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Interlocked.Exchange(ref _isProcessingFrame, 0);
|
||||
_logger?.Error(ex, "图像转换失败:{Message}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 16 位灰度数据线性拉伸为 8 位 BitmapSource(委托给 XP.Common 通用转换器)
|
||||
/// </summary>
|
||||
private static BitmapSource ConvertToBitmapSource(ushort[] data, int width, int height)
|
||||
{
|
||||
return XP.Common.Converters.ImageConverter.ConvertGray16ToBitmapSource(data, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,4 +19,4 @@
|
||||
</Border>
|
||||
<views:PipelineEditorView Grid.Row="1" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
|
||||
xmlns:views="clr-namespace:XplorePlane.Views"
|
||||
xmlns:views1="clr-namespace:XP.Hardware.RaySource.Views;assembly=XP.Hardware.RaySource"
|
||||
xmlns:mcViews="clr-namespace:XP.Hardware.MotionControl.Views;assembly=XP.Hardware.MotionControl"
|
||||
x:Name="ParentWindow"
|
||||
Title="XplorePlane"
|
||||
Width="1920"
|
||||
Height="1040"
|
||||
d:DesignWidth="1580"
|
||||
Background="#F5F5F5"
|
||||
Icon="pack://application:,,,/GapInspect.ico"
|
||||
Icon="pack://application:,,,/XplorerPlane.ico"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
@@ -196,10 +197,7 @@
|
||||
<telerik:RadRibbonToggleButton
|
||||
telerik:ScreenTip.Description="暖机"
|
||||
telerik:ScreenTip.Title="暖机"
|
||||
Command="{Binding Path=SetIsWrapped.Command}"
|
||||
CommandParameter="{Binding Path=SetIsWrapped.SelectedValue}"
|
||||
IsChecked="{Binding Path=SetIsWrapped.SelectedValue, Mode=TwoWay}"
|
||||
IsEnabled="{Binding Path=SetIsWrapped.IsEnabled}"
|
||||
Command="{Binding WarmUpCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/heat-engine.png"
|
||||
Text="暖机" />
|
||||
@@ -207,10 +205,7 @@
|
||||
x:Name="MergeAndCenterButton"
|
||||
telerik:ScreenTip.Description="轴复位"
|
||||
telerik:ScreenTip.Title="轴复位"
|
||||
Command="{Binding Path=MergeAndCenter.Command}"
|
||||
CommandParameter="{Binding Path=MergeAndCenter.SelectedValue}"
|
||||
IsChecked="{Binding Path=MergeAndCenter.SelectedValue, Mode=TwoWay}"
|
||||
IsEnabled="{Binding Path=MergeAndCenter.IsEnabled}"
|
||||
Command="{Binding AxisResetCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/home.png"
|
||||
Text="轴复位" />
|
||||
@@ -222,10 +217,7 @@
|
||||
x:Name="MergeAndCenterButton1"
|
||||
telerik:ScreenTip.Description="射线源控制"
|
||||
telerik:ScreenTip.Title="射线源"
|
||||
Command="{Binding Path=MergeAndCenter.Command}"
|
||||
CommandParameter="{Binding Path=MergeAndCenter.SelectedValue}"
|
||||
IsChecked="{Binding Path=MergeAndCenter.SelectedValue, Mode=TwoWay}"
|
||||
IsEnabled="{Binding Path=MergeAndCenter.IsEnabled}"
|
||||
Command="{Binding OpenRaySourceConfigCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/xray.png"
|
||||
Text="射线源" />
|
||||
@@ -233,10 +225,7 @@
|
||||
x:Name="MergeAndCenterButton2"
|
||||
telerik:ScreenTip.Description="探测器控制"
|
||||
telerik:ScreenTip.Title="探测器"
|
||||
Command="{Binding Path=MergeAndCenter.Command}"
|
||||
CommandParameter="{Binding Path=MergeAndCenter.SelectedValue}"
|
||||
IsChecked="{Binding Path=MergeAndCenter.SelectedValue, Mode=TwoWay}"
|
||||
IsEnabled="{Binding Path=MergeAndCenter.IsEnabled}"
|
||||
Command="{Binding OpenDetectorConfigCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/detector2.png"
|
||||
Text="探测器" />
|
||||
@@ -244,24 +233,28 @@
|
||||
x:Name="MergeAndCenterButton3"
|
||||
telerik:ScreenTip.Description="运动控制"
|
||||
telerik:ScreenTip.Title="运动控制"
|
||||
Command="{Binding Path=MergeAndCenter.Command}"
|
||||
CommandParameter="{Binding Path=MergeAndCenter.SelectedValue}"
|
||||
IsChecked="{Binding Path=MergeAndCenter.SelectedValue, Mode=TwoWay}"
|
||||
IsEnabled="{Binding Path=MergeAndCenter.IsEnabled}"
|
||||
Command="{Binding OpenMotionDebugCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/xyz.png"
|
||||
Text="运动控制" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- 第三列: 相机设置 -->
|
||||
<!-- 第三列: 相机设置 / PLC 地址配置 -->
|
||||
<StackPanel>
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Description="打开相机参数设置对话框"
|
||||
telerik:ScreenTip.Title="相机设置"
|
||||
Click="CameraSettings_Click"
|
||||
Command="{Binding OpenCameraSettingsCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/detector2.png"
|
||||
Text="相机设置" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Description="打开 PLC 信号地址定义编辑器"
|
||||
telerik:ScreenTip.Title="PLC 地址配置"
|
||||
Command="{Binding OpenPlcAddrConfigCommand}"
|
||||
Size="Medium"
|
||||
SmallImage="/Assets/Icons/tools.png"
|
||||
Text="PLC 地址" />
|
||||
</StackPanel>
|
||||
</telerik:RadRibbonGroup>
|
||||
|
||||
@@ -269,7 +262,7 @@
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Description="打开算子工具箱,拖拽算子到流水线中"
|
||||
telerik:ScreenTip.Title="算子工具箱"
|
||||
Click="OpenToolboxButton_Click"
|
||||
Command="{Binding OpenToolboxCommand}"
|
||||
Size="Large"
|
||||
SmallImage="/Assets/Icons/dynamic-range.png"
|
||||
Text="算子工具箱" />
|
||||
@@ -411,7 +404,7 @@
|
||||
<telerik:RadRibbonButton
|
||||
Size="Large"
|
||||
SmallImage="/Assets/Icons/tools.png"
|
||||
Click="LibraryVersions_Click"
|
||||
Command="{Binding OpenLibraryVersionsCommand}"
|
||||
Text="关于 XplorePlane" />
|
||||
</telerik:RadRibbonGroup>
|
||||
<telerik:RadRibbonGroup Header="帮助">
|
||||
@@ -421,8 +414,28 @@
|
||||
<telerik:RadRibbonButton
|
||||
Size="Large"
|
||||
SmallImage="/Assets/Icons/message.png"
|
||||
Command="{Binding OpenUserManualCommand}"
|
||||
Text="帮助文档" />
|
||||
</telerik:RadRibbonGroup>
|
||||
<telerik:RadRibbonGroup Header="设置">
|
||||
<telerik:RadRibbonGroup.Variants>
|
||||
<telerik:GroupVariant Priority="0" Variant="Large" />
|
||||
</telerik:RadRibbonGroup.Variants>
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Description="切换应用程序显示语言"
|
||||
telerik:ScreenTip.Title="多语言设置"
|
||||
Size="Large"
|
||||
SmallImage="/Assets/Icons/tools.png"
|
||||
Command="{Binding OpenLanguageSwitcherCommand}"
|
||||
Text="多语言设置" />
|
||||
<telerik:RadRibbonButton
|
||||
telerik:ScreenTip.Description="打开实时日志查看器"
|
||||
telerik:ScreenTip.Title="查看日志"
|
||||
Size="Large"
|
||||
SmallImage="/Assets/Icons/message.png"
|
||||
Command="{Binding OpenRealTimeLogViewerCommand}"
|
||||
Text="查看日志" />
|
||||
</telerik:RadRibbonGroup>
|
||||
</telerik:RadRibbonTab>
|
||||
|
||||
<telerik:RadRibbonView.ContextualGroups>
|
||||
@@ -473,16 +486,12 @@
|
||||
<ColumnDefinition Width="250*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="250" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="340" />
|
||||
</Grid.RowDefinitions>
|
||||
<views1:RaySourceOperateView Grid.Row="0" Grid.ColumnSpan="2" />
|
||||
<views:MotionControlPanelView
|
||||
Grid.Row="1"
|
||||
Grid.RowSpan="2"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0,0,0,10" />
|
||||
<mcViews:MotionControlView Grid.Row="1" Grid.ColumnSpan="2"/>
|
||||
<views:NavigationPropertyPanelView Grid.Row="2" Grid.ColumnSpan="2" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Prism.Ioc;
|
||||
using System.Windows;
|
||||
using XplorePlane.ViewModels;
|
||||
|
||||
@@ -21,42 +20,5 @@ namespace XplorePlane.Views
|
||||
NavigationPanel.Visibility = show ? Visibility.Visible : Visibility.Collapsed;
|
||||
NavColumn.Width = show ? new GridLength(180) : new GridLength(0);
|
||||
}
|
||||
|
||||
private OperatorToolboxWindow _toolboxWindow;
|
||||
|
||||
private void OpenToolboxButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_toolboxWindow == null || !_toolboxWindow.IsLoaded)
|
||||
{
|
||||
_toolboxWindow = new OperatorToolboxWindow { Owner = this };
|
||||
_toolboxWindow.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
_toolboxWindow.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
private void CameraSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var bootstrapper = AppBootstrapper.Instance;
|
||||
if (bootstrapper == null) return;
|
||||
|
||||
var vm = bootstrapper.Container.Resolve<NavigationPropertyPanelViewModel>();
|
||||
if (!vm.IsCameraConnected)
|
||||
{
|
||||
MessageBox.Show("请先连接相机", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var window = new CameraSettingsWindow(vm) { Owner = this };
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private void LibraryVersions_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = new LibraryVersionsWindow { Owner = this };
|
||||
window.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
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:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
d:DesignHeight="400"
|
||||
d:DesignWidth="600"
|
||||
mc:Ignorable="d">
|
||||
@@ -11,26 +13,28 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Border
|
||||
Grid.Row="0"
|
||||
Background="#F0F0F0"
|
||||
BorderBrush="#DDDDDD"
|
||||
BorderThickness="0,0,0,1">
|
||||
<TextBlock
|
||||
Margin="8,4"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#333333"
|
||||
Text="实时图像" />
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<Border Grid.Row="0" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,0,0,1">
|
||||
<TextBlock Margin="8,4" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
FontWeight="SemiBold" Foreground="#333333" Text="实时图像" />
|
||||
</Border>
|
||||
|
||||
<!-- 图像显示区域,支持滚动 -->
|
||||
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||
<Image Source="{Binding ImageSource}"
|
||||
Stretch="None"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
RenderOptions.BitmapScalingMode="NearestNeighbor" />
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- 图像信息栏 -->
|
||||
<Border Grid.Row="2" Background="#F0F0F0" BorderBrush="#DDDDDD" BorderThickness="0,1,0,0">
|
||||
<TextBlock Margin="8,2" FontSize="11" Foreground="#666666"
|
||||
Text="{Binding ImageInfo}" />
|
||||
</Border>
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
Foreground="#999999"
|
||||
Text="2D Viewport" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
<RootNamespace>XplorePlane</RootNamespace>
|
||||
<AssemblyName>XplorePlane</AssemblyName>
|
||||
<ApplicationIcon>GapInspect.ico</ApplicationIcon>
|
||||
<ApplicationIcon>XplorerPlane.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -37,15 +37,6 @@
|
||||
<!-- DLL 引用 -->
|
||||
<ItemGroup>
|
||||
<!-- 硬件库 DLL 引用 -->
|
||||
<Reference Include="XP.Common">
|
||||
<HintPath>Libs\Hardware\XP.Common.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
|
||||
<Reference Include="XP.Hardware.RaySource">
|
||||
<HintPath>Libs\Hardware\XP.Hardware.RaySource.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
|
||||
<!-- 原生依赖库引用 -->
|
||||
<Reference Include="BR.AN.PviServices">
|
||||
@@ -154,7 +145,7 @@
|
||||
<Link>Libs\Hardware\zh-TW\%(Filename)%(Extension)</Link>
|
||||
</None>
|
||||
|
||||
<Resource Include="GapInspect.ico" />
|
||||
<Resource Include="XplorerPlane.ico" />
|
||||
|
||||
<!-- 配置文件 -->
|
||||
<None Update="App.config">
|
||||
@@ -162,6 +153,10 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\XP.Common\XP.Common.csproj" />
|
||||
<ProjectReference Include="..\XP.Hardware.Detector\XP.Hardware.Detector.csproj" />
|
||||
<ProjectReference Include="..\XP.Hardware.MotionControl\XP.Hardware.MotionControl.csproj" />
|
||||
<ProjectReference Include="..\XP.Hardware.RaySource\XP.Hardware.RaySource.csproj" />
|
||||
<ProjectReference Include="..\XP.ImageProcessing.CfgControl\XP.ImageProcessing.CfgControl.csproj" />
|
||||
<ProjectReference Include="..\XP.ImageProcessing.Core\XP.ImageProcessing.Core.csproj" />
|
||||
<ProjectReference Include="..\XP.ImageProcessing.Processors\XP.ImageProcessing.Processors.csproj" />
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Reference in New Issue
Block a user