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);