From ad398652a7721e21bba788e4c4fe576877707d11 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sun, 31 May 2026 14:59:54 +0800 Subject: [PATCH] feat: alias persistence via PathDatabase SQLite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AliasTreePlugin 监听文档生命周期,连接 PathDatabase - AliasDataStore 写入 PathDatabase.SQLiteConnection - 编辑别名实时持久化,重启后自动恢复 - 修复 _isInternalSelection 阻塞 _currentSelectionItem 更新导致编辑写错节点 --- src/Core/AliasTree/AliasTreePlugin.cs | 74 ++++++++++++++++++----- src/UI/WPF/Views/AliasTreeControl.xaml.cs | 29 +++++++-- 2 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/Core/AliasTree/AliasTreePlugin.cs b/src/Core/AliasTree/AliasTreePlugin.cs index 388d629..299141a 100644 --- a/src/Core/AliasTree/AliasTreePlugin.cs +++ b/src/Core/AliasTree/AliasTreePlugin.cs @@ -2,36 +2,30 @@ using Autodesk.Navisworks.Api.Plugins; using NavisworksTransport.UI.WPF.Views; using NavisworksTransport.Utils; using System.Windows.Forms.Integration; +using NavisApplication = Autodesk.Navisworks.Api.Application; namespace NavisworksTransport.Core.AliasTree { - /// - /// 别名导航树 — DockPanePlugin 入口 - /// - /// 使用方式: - /// 1. 启动 Navisworks - /// 2. View → Docking Windows → 别名导航树 - /// 3. 手动拖放到内置 Selection Tree 下方 - /// [Plugin("NavisworksTransport.AliasTree", "Tian", DisplayName = "别名导航树", ToolTip = "自定义节点别名管理面板 — 双击编辑、右键菜单、JSON 导入导出")] [DockPanePlugin(300, 400, FixedSize = false, AutoScroll = true)] public class AliasTreePlugin : DockPanePlugin { + private AliasTreeControl _control; + public override System.Windows.Forms.Control CreateControlPane() { LogManager.Info("[别名树] 创建 DockPane 面板"); - var eh = new ElementHost - { - AutoSize = true - }; - - var control = new AliasTreeControl(); - eh.Child = control; + var eh = new ElementHost { AutoSize = true }; + _control = new AliasTreeControl(); + eh.Child = _control; eh.CreateControl(); + // 面板创建时如果文档已存在,立即连接数据库 + TryConnectToDatabase(); + return eh; } @@ -45,7 +39,57 @@ namespace NavisworksTransport.Core.AliasTree eh.Child = null; } + _control = null; pane?.Dispose(); } + + protected override void OnLoaded() + { + base.OnLoaded(); + NavisApplication.ActiveDocumentChanged += OnDocumentChanged; + } + + protected override void OnUnloading() + { + NavisApplication.ActiveDocumentChanged -= OnDocumentChanged; + base.OnUnloading(); + } + + private void OnDocumentChanged(object sender, System.EventArgs e) + { + TryConnectToDatabase(); + } + + private void TryConnectToDatabase() + { + if (_control == null) return; + + try + { + var doc = NavisApplication.ActiveDocument; + if (doc == null || string.IsNullOrEmpty(doc.FileName)) + { + _control.SetDataStore(null); + return; + } + + var pathManager = PathPlanningManager.GetActivePathManager(); + var db = pathManager?.GetPathDatabase(); + if (db?.Connection == null) + { + LogManager.Warning("[别名树] PathDatabase 未就绪,等待文档加载完成"); + return; + } + + var store = new AliasDataStore(db.Connection); + store.EnsureTableExists(); + _control.SetDataStore(store); + LogManager.Info("[别名树] 已连接别名数据库"); + } + catch (System.Exception ex) + { + LogManager.Error($"[别名树] 连接数据库失败: {ex.Message}"); + } + } } } diff --git a/src/UI/WPF/Views/AliasTreeControl.xaml.cs b/src/UI/WPF/Views/AliasTreeControl.xaml.cs index 7d3e472..37476ab 100644 --- a/src/UI/WPF/Views/AliasTreeControl.xaml.cs +++ b/src/UI/WPF/Views/AliasTreeControl.xaml.cs @@ -56,7 +56,25 @@ namespace NavisworksTransport.UI.WPF.Views public void SetDataStore(AliasDataStore store) { _dataStore = store; - RebuildTree(); + if (!_built) + RebuildTree(); + else + RefreshAliasesFromStore(); + } + + /// + /// 从 AliasDataStore 刷新所有节点的别名显示(不重建树) + /// + private void RefreshAliasesFromStore() + { + if (_dataStore == null) return; + + var aliasMap = _dataStore.LoadAll(); + foreach (var kvp in aliasMap) + { + if (_nodeMap.TryGetValue(kvp.Key, out var node)) + node.Alias = kvp.Value; + } } /// @@ -141,8 +159,6 @@ namespace NavisworksTransport.UI.WPF.Views /// private void OnNavisSelectionChanged(object sender, EventArgs e) { - if (_isInternalSelection) return; - Dispatcher.BeginInvoke(new Action(() => { try @@ -160,8 +176,9 @@ namespace NavisworksTransport.UI.WPF.Views LogManager.Info($"[别名树] NW选中: DisplayName={item.DisplayName}, ClassName={item.ClassName}"); - // 在树中展开并高亮 - ExpandAndSelect(item); + // 内部触发时不展开(别名树点击引起的),只更新 _currentSelectionItem + if (!_isInternalSelection) + ExpandAndSelect(item); } else { @@ -603,6 +620,7 @@ namespace NavisworksTransport.UI.WPF.Views if (string.IsNullOrEmpty(input)) return; var identity = AliasNodeIdentity.FromModelItem(_currentSelectionItem); + LogManager.Info($"[别名树] 保存别名: {input}, NodeKey={identity.ToKey()}"); _dataStore.SetAlias(identity, input); TxtAliasInput.Clear(); @@ -707,6 +725,7 @@ namespace NavisworksTransport.UI.WPF.Views if (textBox?.DataContext is AliasNodeViewModel node) { string newAlias = textBox.Text?.Trim(); + LogManager.Info($"[别名树] 内联编辑: {newAlias}, NodeKey={node.NodeKey}"); if (_dataStore != null) { AliasNodeIdentity.TryParseKey(node.NodeKey, out var identity);