NavisworksTransport/src/Core/MainPlugin.cs

883 lines
34 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Autodesk.Navisworks.Api.Plugins;
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Animation;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Utils;
using NavisworksTransport.Utils.CoordinateSystem;
using NavisApplication = Autodesk.Navisworks.Api.Application;
namespace NavisworksTransport
{
/// <summary>
/// 物流属性变更事件参数
/// </summary>
public class LogisticsAttributeChangedEventArgs : EventArgs
{
public string OperationType { get; set; } // "修改" 或 "删除"
public int AffectedCount { get; set; } // 受影响的模型数量
public string Message { get; set; } // 操作描述信息
public LogisticsAttributeChangedEventArgs(string operationType, int affectedCount, string message = "")
{
OperationType = operationType;
AffectedCount = affectedCount;
Message = message;
}
}
/// <summary>
/// 全局异常处理工具类
/// </summary>
public static class GlobalExceptionHandler
{
private static bool _isInitialized = false;
/// <summary>
/// 初始化全局异常处理器
/// </summary>
public static void Initialize()
{
if (_isInitialized) return;
try
{
// 捕获未处理的异常
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
// 捕获任务调度器未观察到的异常
System.Threading.Tasks.TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
// 直接注册WinForms线程异常处理器不调用SetUnhandledExceptionMode避免插件环境下的警告
System.Windows.Forms.Application.ThreadException += OnThreadException;
_isInitialized = true;
LogManager.Info("[全局异常] 全局异常处理器已初始化");
}
catch (Exception ex)
{
LogManager.Error($"[全局异常] 初始化异常处理器失败: {ex.Message}");
}
}
/// <summary>
/// 处理未捕获的异常
/// </summary>
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = e.ExceptionObject as Exception;
string message = ex?.Message ?? "未知异常";
string stackTrace = ex?.StackTrace ?? "无堆栈信息";
LogManager.Error($"[全局异常] ===== 未处理异常发生 =====");
LogManager.Error($"[全局异常] 异常类型: {ex?.GetType().FullName ?? "Unknown"}");
LogManager.Error($"[全局异常] 异常消息: {message}");
LogManager.Error($"[全局异常] 是否终止进程: {e.IsTerminating}");
LogManager.Error($"[全局异常] 当前线程ID: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
LogManager.Error($"[全局异常] 当前线程名称: {System.Threading.Thread.CurrentThread.Name ?? ""}");
// 检查是否为特定类型的异常
if (ex is OutOfMemoryException)
{
LogManager.Error($"[全局异常] ⚠️ 内存不足异常");
var memoryUsage = GC.GetTotalMemory(false);
LogManager.Error($"[全局异常] 当前内存使用: {memoryUsage / 1024 / 1024:F1} MB");
}
else if (ex is StackOverflowException)
{
LogManager.Error($"[全局异常] ⚠️ 堆栈溢出异常");
}
else if (ex is AccessViolationException)
{
LogManager.Error($"[全局异常] ⚠️ 访问违规异常");
}
else if (ex is System.Runtime.InteropServices.SEHException)
{
LogManager.Error($"[全局异常] ⚠️ 结构化异常处理异常");
}
LogManager.Error($"[全局异常] 堆栈跟踪:");
LogManager.Error(stackTrace);
if (ex?.InnerException != null)
{
LogManager.Error($"[全局异常] 内部异常: {ex.InnerException.GetType().Name}: {ex.InnerException.Message}");
LogManager.Error($"[全局异常] 内部异常堆栈: {ex.InnerException.StackTrace}");
}
// 显示用户友好的错误信息
ShowErrorDialog("程序发生未预期的错误", message, ex);
// 尝试恢复关键组件
TryRecoverComponents();
LogManager.Error($"[全局异常] ===== 异常处理完成 =====");
}
catch
{
// 异常处理中的异常,保持静默
}
}
/// <summary>
/// 处理未观察到的任务异常
/// </summary>
private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
try
{
Exception ex = e.Exception;
LogManager.Error($"[全局异常] 未观察任务异常: {ex.Message}");
LogManager.Error($"[全局异常] 堆栈信息: {ex.StackTrace}");
LogManager.Error($"[全局异常] 异常类型: {ex.GetType().Name}");
// 标记异常已被观察,防止应用程序终止
e.SetObserved();
// 显示用户友好的错误信息
ShowErrorDialog("程序发生后台任务错误", ex.Message, ex);
// 尝试恢复关键组件
TryRecoverComponents();
}
catch
{
// 异常处理中的异常,保持静默
}
}
/// <summary>
/// 处理线程异常
/// </summary>
private static void OnThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
try
{
Exception ex = e.Exception;
LogManager.Error($"[全局异常] 线程异常: {ex.Message}");
LogManager.Error($"[全局异常] 堆栈信息: {ex.StackTrace}");
LogManager.Error($"[全局异常] 异常类型: {ex.GetType().Name}");
// 显示用户友好的错误信息
ShowErrorDialog("程序发生线程错误", ex.Message, ex);
// 尝试恢复关键组件
TryRecoverComponents();
}
catch
{
// 异常处理中的异常,保持静默
}
}
/// <summary>
/// 安全执行方法,捕获所有异常
/// </summary>
public static T SafeExecute<T>(Func<T> action, T defaultValue = default, string operationName = "操作")
{
try
{
return action();
}
catch (Exception ex)
{
LogManager.Error($"[安全执行] {operationName}失败: {ex.Message}");
LogManager.Error($"[安全执行] 堆栈信息: {ex.StackTrace}");
LogManager.Error($"[安全执行] 异常类型: {ex.GetType().Name}");
// 对于用户操作,显示简短的错误提示
if (!string.IsNullOrEmpty(operationName) && operationName != "操作")
{
ShowErrorToast($"{operationName}失败: {ex.Message}");
}
return defaultValue;
}
}
/// <summary>
/// 安全执行方法(无返回值)
/// </summary>
public static void SafeExecute(Action action, string operationName = "操作")
{
SafeExecute(() => { action(); return true; }, false, operationName);
}
/// <summary>
/// 显示错误对话框
/// </summary>
private static void ShowErrorDialog(string title, string message, Exception ex = null)
{
try
{
string detailMessage = message;
if (ex != null)
{
detailMessage += $"\n\n技术详情: {ex.GetType().Name}";
if (!string.IsNullOrEmpty(ex.Message))
{
detailMessage += $"\n错误信息: {ex.Message}";
}
}
MessageBox.Show(detailMessage, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch
{
// 如果连错误对话框都显示不了,就保持静默
}
}
/// <summary>
/// 显示简短的错误提示
/// </summary>
private static void ShowErrorToast(string message)
{
try
{
MessageBox.Show(message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch
{
// 保持静默
}
}
/// <summary>
/// 清理 Clash Detective 集成相关资源
/// </summary>
public static void CleanupClashDetectiveIntegration()
{
try
{
LogManager.Info("[清理] 开始清理 Clash Detective 集成...");
// 清理 Clash Detective 集成
ClashDetectiveIntegration.Instance.Cleanup();
LogManager.Info("[清理] Clash Detective 集成清理完成");
}
catch (Exception ex)
{
LogManager.Error($"[清理] Clash Detective 集成清理失败: {ex.Message}");
}
}
/// <summary>
/// 尝试恢复关键组件
/// </summary>
private static void TryRecoverComponents()
{
try
{
LogManager.Info("[全局异常] 尝试恢复关键组件...");
// 尝试重置路径编辑状态
var activeManager = PathPlanningManager.GetActivePathManager();
if (activeManager != null)
{
activeManager.ResetPathEditState();
LogManager.Info("[全局异常] 已重置路径编辑状态");
}
// 尝试清除临时高亮
if (NavisApplication.ActiveDocument?.Models != null)
{
ModelHighlightHelper.ClearAllHighlights();
LogManager.Info("[全局异常] 已清除临时材质");
}
// 清理 Clash Detective 集成
CleanupClashDetectiveIntegration();
LogManager.Info("[全局异常] 组件恢复完成");
}
catch (Exception ex)
{
LogManager.Error($"[全局异常] 组件恢复失败: {ex.Message}");
}
}
}
[Plugin("NavisworksTransport.Main", "Tian",
DisplayName = "物流路径规划",
ToolTip = "物流路径规划和动画仿真插件")]
[DockPanePlugin(420, 700, FixedSize = false, AutoScroll = true)]
public class Main : DockPanePlugin
{
/// <summary>
/// 构造函数,提前初始化全局异常处理器
/// </summary>
// 状态跟踪变量用于观察Models.CollectionChanged事件
private bool _hasModels = false;
private int _eventCount = 0;
private DateTime _pluginStartTime = DateTime.Now;
public Main()
{
// 在任何控件创建之前初始化全局异常处理器
GlobalExceptionHandler.Initialize();
}
/// <summary>
/// 插件加载后调用Navisworks插件生命周期
/// </summary>
protected override void OnLoaded()
{
base.OnLoaded();
_pluginStartTime = DateTime.Now; // 记录插件启动时间
LogManager.Info("[文档管理] 插件OnLoaded - 开始初始化");
//显式初始化配置管理器,确保配置加载完成
try
{
var config = ConfigManager.Instance.Current;
LogManager.Info($"[配置管理] 配置已加载");
// 检查配置兼容性
if (ConfigManager.Instance.HasMissingConfigItems)
{
var message = ConfigManager.Instance.GetConfigCompatibilityMessage();
LogManager.Warning($"[配置管理] {message}");
// 延迟显示配置兼容性提示(避免在插件加载时阻塞)
Task.Delay(3000).ContinueWith(_ =>
{
try
{
// 使用 Navisworks 的 API 显示消息框
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
System.Windows.MessageBox.Show(
message,
"配置文件需要升级",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Warning);
});
}
catch (Exception msgEx)
{
LogManager.Error($"[配置管理] 显示兼容性提示失败: {msgEx.Message}");
}
});
}
// 注意:坐标系初始化推迟到 InitializeManagers() 中进行
// 因为此时文档可能尚未加载,无法正确检测坐标系
}
catch (Exception ex)
{
LogManager.Error($"[配置管理] 配置加载失败: {ex.Message}");
}
// 订阅文档事件
SubscribeToDocumentEvents();
// 检查是否已有活动文档且包含模型
var activeDoc = NavisApplication.ActiveDocument;
if (activeDoc != null && activeDoc.Models != null && activeDoc.Models.Count > 0)
{
LogManager.Info("[文档管理] 插件加载时发现包含模型的活动文档,立即初始化管理器");
InitializeManagers();
}
else if (activeDoc != null)
{
LogManager.Info("[文档管理] 插件加载时发现空文档(无模型),等待文档加载完成");
}
else
{
LogManager.Info("[文档管理] 插件加载时无活动文档");
}
}
/// <summary>
/// 插件卸载前调用Navisworks插件生命周期
/// </summary>
protected override void OnUnloading()
{
LogManager.Info("[文档管理] 插件OnUnloading - 开始清理");
// 取消订阅文档事件
UnsubscribeFromDocumentEvents();
// 清理管理器
CleanupManagers();
base.OnUnloading();
}
/// <summary>
/// 订阅文档相关事件
/// </summary>
private void SubscribeToDocumentEvents()
{
try
{
// 订阅文档切换前事件(保留用于未来兼容性)
NavisApplication.ActiveDocumentChanging += OnActiveDocumentChanging;
// 订阅文档切换后事件(保留用于未来兼容性)
NavisApplication.ActiveDocumentChanged += OnActiveDocumentChanged;
// 订阅模型集合变化事件SDI架构下的真正文档变化事件
if (NavisApplication.ActiveDocument != null)
{
NavisApplication.ActiveDocument.Models.CollectionChanged += OnModelsCollectionChanged;
LogManager.Info("[文档管理] 已订阅模型集合变化事件");
}
LogManager.Info("[文档管理] 已订阅文档相关事件Changing + Changed + Models.CollectionChanged");
}
catch (Exception ex)
{
LogManager.Error($"[文档管理] 订阅文档事件失败: {ex.Message}");
}
}
/// <summary>
/// 活动文档切换前事件处理
/// </summary>
private void OnActiveDocumentChanging(object sender, EventArgs e)
{
LogManager.Info($"[文档管理] 文档即将切换,当前文档: {NavisApplication.ActiveDocument?.FileName ?? ""}");
// 取消订阅旧文档的Models.CollectionChanged事件
if (NavisApplication.ActiveDocument != null)
{
try
{
NavisApplication.ActiveDocument.Models.CollectionChanged -= OnModelsCollectionChanged;
LogManager.Info("[文档管理] 已取消订阅旧文档的模型集合变化事件");
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 取消订阅旧文档事件时出现警告: {ex.Message}");
}
}
// 清理旧文档的状态
CleanupManagers();
}
/// <summary>
/// 活动文档切换事件处理
/// </summary>
private void OnActiveDocumentChanged(object sender, EventArgs e)
{
LogManager.Info($"[文档管理] 文档已切换到: {NavisApplication.ActiveDocument?.FileName ?? ""}");
// 清除单位转换缓存(文档切换后单位可能不同)
Utils.UnitsConverter.ClearCache();
GlobalExceptionHandler.SafeExecute(() =>
{
var activeDoc = NavisApplication.ActiveDocument;
// 如果有新的活动文档订阅其Models.CollectionChanged事件
if (activeDoc != null)
{
try
{
activeDoc.Models.CollectionChanged += OnModelsCollectionChanged;
LogManager.Info("[文档管理] 已订阅新文档的模型集合变化事件");
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 订阅新文档事件时出现警告: {ex.Message}");
}
InitializeManagers();
}
else
{
LogManager.Info("[文档管理] 当前无活动文档");
}
}, "处理活动文档切换事件");
}
/// <summary>
/// 模型集合变化事件处理
/// </summary>
private void OnModelsCollectionChanged(object sender, EventArgs e)
{
_eventCount++;
var activeDoc = NavisApplication.ActiveDocument;
var modelCount = activeDoc?.Models?.Count ?? 0;
bool currentHasModels = modelCount > 0;
var timeSinceStart = (DateTime.Now - _pluginStartTime).TotalSeconds;
LogManager.Info("========================================");
LogManager.Info($"[文档管理] Models.CollectionChanged 事件 #{_eventCount}");
LogManager.Info($"[文档管理] 触发时间: 插件启动后 {timeSinceStart:F1} 秒");
LogManager.Info($"[文档管理] 当前Models.Count = {modelCount}");
LogManager.Info($"[文档管理] 状态变化: {(_hasModels ? "" : "")} -> {(currentHasModels ? "" : "")}");
LogManager.Info($"[文档管理] 文档文件名: {activeDoc?.FileName ?? ""}");
LogManager.Info($"[文档管理] 文档标题: {activeDoc?.Title ?? ""}");
// 分析状态变化类型并执行相应操作
if (!_hasModels && currentHasModels)
{
LogManager.Info($"[文档管理] *** 状态分析: 从无到有(可能是打开文档)***");
// 文档加载完成初始化PathDatabase
if (!string.IsNullOrEmpty(activeDoc?.FileName))
{
try
{
var pathManager = PathPlanningManager.GetActivePathManager();
if (pathManager != null)
{
pathManager.DatabaseInitialize();
}
}
catch (Exception ex)
{
// 数据库初始化失败是严重错误,需要明确提示用户
var errorMsg = $"数据库初始化失败:{ex.Message}\n\n";
errorMsg += "可能的原因:\n";
errorMsg += "1. 文件夹权限不足\n";
errorMsg += "2. 磁盘空间不足\n";
errorMsg += "3. 数据库文件被锁定\n";
errorMsg += "4. SQLite 组件损坏\n\n";
errorMsg += "详细信息请查看日志文件。";
LogManager.Error($"[文档管理] 数据库初始化失败: {ex.Message}", ex);
LogManager.Error($"[文档管理] 文档路径: {activeDoc.FileName}");
LogManager.Error($"[文档管理] 异常类型: {ex.GetType().Name}");
LogManager.Error($"[文档管理] 堆栈信息: {ex.StackTrace}");
System.Windows.MessageBox.Show(
errorMsg,
"数据库初始化失败",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error
);
// 不重新抛出,避免插件崩溃,但批处理等功能将不可用
}
}
}
else if (_hasModels && !currentHasModels)
{
LogManager.Info($"[文档管理] *** 状态分析: 从有到无(可能是关闭文档)***");
}
else if (!_hasModels && !currentHasModels)
{
LogManager.Info($"[文档管理] *** 状态分析: 保持无模型状态 ***");
}
else if (_hasModels && currentHasModels)
{
LogManager.Info($"[文档管理] *** 状态分析: 保持有模型状态(模型数量变化)***");
}
LogManager.Info("========================================");
// 更新状态
_hasModels = currentHasModels;
}
/// <summary>
/// 为当前文档初始化坐标系
/// 在文档加载完成后调用,确保可以正确检测 Document.UpVector
/// </summary>
private void InitializeCoordinateSystemForDocument()
{
try
{
var config = ConfigManager.Instance.Current;
if (config?.CoordinateSystem == null)
{
LogManager.Warning("[坐标系] 配置中缺少坐标系设置,使用默认自动检测");
CoordinateSystemManager.Instance.Initialize(CoordinateSystemType.AutoDetect);
return;
}
// 如果已经初始化且不是 AutoDetect 模式,则跳过
// 这样用户手动设置的坐标系不会在文档切换时被覆盖
if (CoordinateSystemManager.Instance.Current != null &&
CoordinateSystemManager.Instance.ConfiguredType != CoordinateSystemType.AutoDetect)
{
LogManager.Debug("[坐标系] 使用手动指定的坐标系,跳过自动检测");
return;
}
// 解析坐标系类型配置
CoordinateSystemType coordType;
var typeString = config.CoordinateSystem.Type?.Trim() ?? "AutoDetect";
switch (typeString.ToLowerInvariant())
{
case "zup":
case "z-up":
coordType = CoordinateSystemType.ZUp;
break;
case "yup":
case "y-up":
coordType = CoordinateSystemType.YUp;
break;
case "autodetect":
case "auto":
default:
coordType = CoordinateSystemType.AutoDetect;
break;
}
// 初始化坐标系
CoordinateSystemManager.Instance.Initialize(coordType);
var currentCS = CoordinateSystemManager.Instance.Current;
LogManager.Info($"[坐标系] 初始化完成 - {currentCS}");
}
catch (Exception ex)
{
LogManager.Error($"[坐标系] 初始化失败: {ex.Message},使用默认 Z-Up");
CoordinateSystemManager.Instance.Initialize(CoordinateSystemType.ZUp);
}
}
/// <summary>
/// 初始化各个管理器
/// </summary>
private void InitializeManagers()
{
try
{
var activeDoc = NavisApplication.ActiveDocument;
if (activeDoc == null)
{
LogManager.Warning("[文档管理] 无活动文档,跳过初始化");
return;
}
LogManager.Info($"[文档管理] 开始为文档 '{activeDoc.FileName ?? ""}' 初始化管理器...");
// 初始化坐标系(文档已加载,可以正确检测)
InitializeCoordinateSystemForDocument();
// 通知DocumentStateManager文档已就绪
DocumentStateManager.Instance.OnDocumentReady();
// 清理并重新初始化各种缓存
ClashDetectiveIntegration.ClearAllCaches();
LogManager.Info("[文档管理] 管理器初始化完成");
}
catch (Exception ex)
{
LogManager.Error($"[文档管理] 初始化管理器失败: {ex.Message}");
}
}
/// <summary>
/// 清理所有管理器状态
/// </summary>
private void CleanupManagers()
{
try
{
LogManager.Info("[文档管理] 开始清理管理器...");
// 通知DocumentStateManager文档已失效
DocumentStateManager.Instance.OnDocumentInvalidated();
// 停止所有动画(程序关闭专用)
try
{
var animationManager = PathAnimationManager.GetInstance();
if (animationManager != null)
{
animationManager.ShutdownAnimation(); // 使用关闭专用方法不执行UI操作
animationManager.ClearReferences();
}
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 清理动画管理器时出现警告: {ex.Message}");
}
// 清理路径规划管理器
try
{
var pathManager = PathPlanningManager.GetActivePathManager();
if (pathManager != null)
{
pathManager.ResetPathEditState();
pathManager.ClearInvalidReferences();
}
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 清理路径管理器时出现警告: {ex.Message}");
}
// 清理路径渲染插件的可视化
try
{
var renderPlugin = PathPointRenderPlugin.Instance;
if (renderPlugin != null)
{
renderPlugin.ClearAllPaths();
LogManager.Info("[文档管理] 已清理路径可视化");
}
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 清理路径可视化时出现警告: {ex.Message}");
}
// 清理碰撞检测缓存
try
{
ClashDetectiveIntegration.Instance?.ClearCollisionCache();
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 清理碰撞检测缓存时出现警告: {ex.Message}");
}
// 清理IdleEventManager任务
try
{
IdleEventManager.Instance?.Dispose();
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 清理Idle事件管理器时出现警告: {ex.Message}");
}
// 清理虚拟车辆
try
{
VirtualVehicleManager.Instance.Cleanup();
LogManager.Info("[文档管理] 已清理虚拟车辆");
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 清理虚拟车辆时出现警告: {ex.Message}");
}
// 清除临时材质
try
{
var activeDoc = NavisApplication.ActiveDocument;
if (activeDoc?.Models != null)
{
ModelHighlightHelper.ClearAllHighlights();
}
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 清除临时材质时出现警告: {ex.Message}");
}
LogManager.Info("[文档管理] 管理器清理完成");
}
catch (Exception ex)
{
LogManager.Error($"[文档管理] 清理管理器失败: {ex.Message}");
}
}
public override Control CreateControlPane()
{
try
{
LogManager.Info("=== 开始创建DockPane控制面板 ===");
// 使用官方示例的最简单实现
LogManager.Info("创建ElementHost...");
ElementHost eh = new ElementHost
{
AutoSize = true
};
LogManager.Info("创建LogisticsControlPanel...");
eh.Child = new UI.WPF.LogisticsControlPanel();
LogManager.Info("调用CreateControl()...");
eh.CreateControl();
LogManager.Info("=== DockPane控制面板创建成功 ===");
return eh;
}
catch (Exception ex)
{
LogManager.Error($"=== CreateControlPane失败: {ex.Message} ===");
LogManager.Error($"异常类型: {ex.GetType().FullName}");
LogManager.Error($"堆栈跟踪: {ex.StackTrace}");
// 返回null会导致Navisworks立即调用DestroyControlPane
throw; // 重新抛出异常让Navisworks知道创建失败
}
}
public override void DestroyControlPane(Control pane)
{
GlobalExceptionHandler.SafeExecute(() =>
{
LogManager.Info("开始销毁DockPane控制面板");
// 清理WPF控件资源
if (pane is ElementHost elementHost && elementHost.Child is UI.WPF.LogisticsControlPanel wpfControl)
{
// 清理WPF控件资源
wpfControl.Cleanup();
elementHost.Child = null;
}
// 取消订阅文档事件
UnsubscribeFromDocumentEvents();
// 释放控件资源
pane?.Dispose();
LogManager.Info("DockPane控制面板销毁完成");
}, "销毁控制面板");
}
/// <summary>
/// 取消订阅文档相关事件
/// </summary>
private void UnsubscribeFromDocumentEvents()
{
try
{
// 取消订阅文档切换事件
NavisApplication.ActiveDocumentChanging -= OnActiveDocumentChanging;
NavisApplication.ActiveDocumentChanged -= OnActiveDocumentChanged;
// 取消订阅当前文档的Models.CollectionChanged事件
if (NavisApplication.ActiveDocument != null)
{
try
{
NavisApplication.ActiveDocument.Models.CollectionChanged -= OnModelsCollectionChanged;
LogManager.Info("[文档管理] 已取消订阅模型集合变化事件");
}
catch (Exception ex)
{
LogManager.Warning($"[文档管理] 取消订阅模型集合事件时出现警告: {ex.Message}");
}
}
LogManager.Info("[文档管理] 已取消订阅所有文档相关事件");
}
catch (Exception ex)
{
LogManager.Error($"[文档管理] 取消订阅文档事件失败: {ex.Message}");
}
}
}
}