修复保存选择集使用旧方法引起的保存整个分层的bug

This commit is contained in:
tian 2025-09-15 19:36:01 +08:00
parent 2cb9475847
commit 034ca80db2

View File

@ -1840,35 +1840,24 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info($"[LayerManagementViewModel] 开始保存选中项目到: {saveFilePath}");
LogManager.Info($"[LayerManagementViewModel] 保存 {originalSelection.Count} 个选中节点及其所有子项");
// 4. 使用基于多选节点的保存逻辑
// 4. 使用借鉴自 ModelSplitterManager.ExportLayerToNwd 的精确隔离逻辑
bool exportResult = false;
string errorMessage = "";
try
{
// 收集所有需要显示的节点(选中的节点和它们的祖先节点)
var nodesToKeepVisible = new HashSet<ModelItem>();
// 对于每个选中的节点,收集它和它的所有祖先节点
// 收集要导出的项目(包含子节点)
var itemsToExport = new List<ModelItem>();
foreach (var selectedItem in originalSelection)
{
// 添加选中节点本身
nodesToKeepVisible.Add(selectedItem);
LogManager.Info($"[LayerManagementViewModel] 添加选中节点到可见列表: {selectedItem.DisplayName}");
// 添加所有祖先节点,确保选中节点的路径可见
var current = selectedItem.Parent;
while (current != null)
{
nodesToKeepVisible.Add(current);
LogManager.Info($"[LayerManagementViewModel] 添加祖先节点到可见列表: {current.DisplayName}");
current = current.Parent;
}
itemsToExport.Add(selectedItem);
LogManager.Info($"[LayerManagementViewModel] 添加选中节点到导出列表: {selectedItem.DisplayName}");
// 添加所有子节点(如果用户开启了包含子节点选项)
if (IncludeChildNodes)
{
// 使用正确的Navisworks API遍历子节点
try
{
// 使用DescendantsAndSelf来获取所有后代节点
@ -1877,7 +1866,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
foreach (ModelItem child in childItems)
{
nodesToKeepVisible.Add(child);
itemsToExport.Add(child);
childCount++;
}
@ -1890,141 +1879,81 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
LogManager.Info($"[LayerManagementViewModel] 总共需要保持可见的节点数量: {nodesToKeepVisible.Count}");
LogManager.Info($"[LayerManagementViewModel] 总共需要导出的节点数量: {itemsToExport.Count}");
// 使用正确的Navisworks API收集顶级节点
// 根据示例,这是正确的方式来获取所有顶级模型项
var allTopLevelItems = new List<ModelItem>();
// 使用RootItemDescendantsAndSelf但只取第一级子项
foreach (Model model in document.Models)
{
foreach (ModelItem topLevelItem in model.RootItem.Children)
{
allTopLevelItems.Add(topLevelItem);
}
}
LogManager.Info($"[LayerManagementViewModel] 收集到 {allTopLevelItems.Count} 个顶级节点");
// 更智能的隐藏策略:
// 1. 如果选中节点包含某个顶级节点或其子节点,则该顶级节点保持可见
// 2. 否则隐藏整个顶级节点分支
var itemsToHide = new ModelItemCollection();
int hiddenCount = 0;
foreach (ModelItem topLevelItem in allTopLevelItems)
{
bool shouldKeepTopLevel = false;
// 检查这个顶级节点或其任何子节点是否需要保持可见
if (nodesToKeepVisible.Contains(topLevelItem))
{
shouldKeepTopLevel = true;
LogManager.Info($"[LayerManagementViewModel] 顶级节点 {topLevelItem.DisplayName} 本身被选中,保持可见");
}
else
{
// 检查是否有任何选中节点是这个顶级节点的后代
foreach (var selectedItem in originalSelection)
{
var current = selectedItem;
while (current != null)
{
if (current == topLevelItem)
{
shouldKeepTopLevel = true;
LogManager.Info($"[LayerManagementViewModel] 顶级节点 {topLevelItem.DisplayName} 包含选中节点,保持可见");
break;
}
current = current.Parent;
}
if (shouldKeepTopLevel) break;
}
}
// 如果这个顶级节点不需要保持可见,则隐藏它
if (!shouldKeepTopLevel)
{
try
{
itemsToHide.Add(topLevelItem);
hiddenCount++;
LogManager.Info($"[LayerManagementViewModel] 隐藏顶级节点: {topLevelItem.DisplayName}");
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 添加隐藏项目失败: {topLevelItem.DisplayName} - {ex.Message}");
}
}
}
// 执行隐藏操作
if (itemsToHide.Count > 0)
// 核心修复:使用与 ModelSplitterManager.ExportLayerToNwd 相同的精确隔离逻辑
// 在主线程中执行 Navisworks API 调用
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
try
{
document.Models.SetHidden(itemsToHide, true);
LogManager.Info($"[LayerManagementViewModel] 成功隐藏 {hiddenCount} 个节点,保留 {nodesToKeepVisible.Count} 个选中节点及其相关节点可见");
LogManager.Info($"[LayerManagementViewModel] 在主线程中执行导出操作");
// 保存当前可见性状态
LogManager.Info($"[LayerManagementViewModel] 开始保存当前可见性状态");
var originalVisibilityState = SaveCurrentVisibilityState(document);
LogManager.Info($"[LayerManagementViewModel] 已保存可见性状态");
try
{
// 使用 VisibilityHelper.IsolateSpecificItems 精确隔离显示
// 这个方法已经在分层导出中验证有效,不会包含额外的祖先节点
LogManager.Info($"[LayerManagementViewModel] 准备隔离显示 {itemsToExport.Count} 个节点");
// 将 List<ModelItem> 转换为 ModelItemCollection
var itemsToIsolate = new ModelItemCollection();
foreach (var item in itemsToExport)
{
itemsToIsolate.Add(item);
}
bool isolateSuccess = VisibilityHelper.IsolateSpecificItems(itemsToIsolate);
if (!isolateSuccess)
{
throw new InvalidOperationException("隔离显示失败");
}
LogManager.Info($"[LayerManagementViewModel] 隔离显示成功");
// 创建导出选项 - 使用用户配置的参数
var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions
{
ExcludeHiddenItems = true, // 只导出可见项目(选中节点及其子项)
EmbedXrefs = EmbedXrefs,
PreventObjectPropertyExport = PreventObjectPropertyExport
};
LogManager.Info($"[LayerManagementViewModel] SaveSelectedItems导出选项: EmbedXrefs={exportOptions.EmbedXrefs}, PreventObjectPropertyExport={exportOptions.PreventObjectPropertyExport}");
LogManager.Info("[LayerManagementViewModel] 开始调用ExportToNwd API");
// 使用ExportToNwd API
document.ExportToNwd(saveFilePath, exportOptions);
exportResult = true;
LogManager.Info("[LayerManagementViewModel] ExportToNwd API调用完成");
}
finally
{
// 恢复原始可见性状态
try
{
RestoreVisibilityState(document, originalVisibilityState);
LogManager.Info("[LayerManagementViewModel] 已恢复原始可见性状态");
}
catch (Exception restoreEx)
{
LogManager.Error($"[LayerManagementViewModel] 恢复可见性失败: {restoreEx.Message}");
}
}
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 隐藏操作失败: {ex.Message}");
LogManager.Error($"[LayerManagementViewModel] 主线程导出异常: {ex.Message}", ex);
errorMessage = ex.Message;
exportResult = false;
}
}
// 确保选中所有目标节点
document.CurrentSelection.Clear();
foreach (var selectedItem in originalSelection)
{
document.CurrentSelection.Add(selectedItem);
}
LogManager.Info($"[LayerManagementViewModel] 已重新选择 {originalSelection.Count} 个目标节点");
// 创建导出选项 - 使用用户配置的参数
var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions
{
ExcludeHiddenItems = true, // 只导出可见项目(选中节点及其子项)
EmbedXrefs = EmbedXrefs,
PreventObjectPropertyExport = PreventObjectPropertyExport
};
LogManager.Info($"[LayerManagementViewModel] SaveSelectedItems导出选项: EmbedXrefs={exportOptions.EmbedXrefs}, PreventObjectPropertyExport={exportOptions.PreventObjectPropertyExport}");
LogManager.Info("[LayerManagementViewModel] 开始调用ExportToNwd API");
// 使用ExportToNwd API
document.ExportToNwd(saveFilePath, exportOptions);
exportResult = true;
LogManager.Info("[LayerManagementViewModel] ExportToNwd API调用完成");
// 恢复所有隐藏项目的可见性
try
{
if (document?.Models != null)
{
// 获取所有模型项并恢复可见性
var allItems = new ModelItemCollection();
foreach (Model model in document.Models)
{
foreach (ModelItem item in model.RootItem.Children)
{
allItems.Add(item);
}
}
if (allItems.Count > 0)
{
document.Models.SetHidden(allItems, false);
LogManager.Info("[LayerManagementViewModel] 已恢复所有项目可见性");
}
}
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 恢复可见性失败: {ex.Message}");
}
});
// 恢复原始选择
try
@ -2110,6 +2039,110 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 保存当前可见性状态
/// </summary>
private Dictionary<ModelItem, bool> SaveCurrentVisibilityState(Document document)
{
var visibilityState = new Dictionary<ModelItem, bool>();
try
{
// 获取所有顶级项目并记录它们的可见性状态
foreach (Model model in document.Models)
{
foreach (ModelItem topLevelItem in model.RootItem.Children)
{
try
{
// 记录是否隐藏IsHidden为true表示隐藏我们存储可见性所以取反
visibilityState[topLevelItem] = !topLevelItem.IsHidden;
}
catch
{
// 如果无法获取状态,默认为可见
visibilityState[topLevelItem] = true;
}
}
}
LogManager.Info($"[LayerManagementViewModel] 保存可见性状态完成,记录了 {visibilityState.Count} 个顶级项目");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 保存可见性状态失败: {ex.Message}");
}
return visibilityState;
}
/// <summary>
/// 恢复可见性状态
/// </summary>
private void RestoreVisibilityState(Document document, Dictionary<ModelItem, bool> visibilityState)
{
try
{
LogManager.Info("[LayerManagementViewModel] 恢复可见性状态");
if (visibilityState == null || visibilityState.Count == 0)
{
LogManager.Warning("[LayerManagementViewModel] 没有可见性状态需要恢复,重置为全部可见");
document.Models.ResetAllHidden();
return;
}
// 使用成熟的可见性控制模式 - 分别收集要显示和隐藏的项目
var itemsToShow = new ModelItemCollection();
var itemsToHide = new ModelItemCollection();
foreach (var kvp in visibilityState)
{
try
{
if (kvp.Value) // 原来是可见的
{
itemsToShow.Add(kvp.Key);
}
else // 原来是隐藏的
{
itemsToHide.Add(kvp.Key);
}
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 处理项目可见性状态时出错: {ex.Message}");
}
}
// 首先重置所有项目为可见状态
document.Models.ResetAllHidden();
// 然后隐藏原来应该隐藏的项目
if (itemsToHide.Count > 0)
{
document.Models.SetHidden(itemsToHide, true);
LogManager.Info($"[LayerManagementViewModel] 恢复隐藏 {itemsToHide.Count} 个项目");
}
LogManager.Info("[LayerManagementViewModel] 可见性状态恢复完成");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 恢复可见性状态失败: {ex.Message}");
// 失败时至少确保模型处于可见状态
try
{
document.Models.ResetAllHidden();
LogManager.Info("[LayerManagementViewModel] 已重置为全部可见状态");
}
catch (Exception resetEx)
{
LogManager.Error($"[LayerManagementViewModel] 重置可见性也失败: {resetEx.Message}");
}
}
}
/// <summary>