using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using Autodesk.Navisworks.Api; using NavisApplication = Autodesk.Navisworks.Api.Application; namespace NavisworksTransport { /// /// 可见性操作结果 /// public class VisibilityOperationResult { /// /// 操作是否成功 /// public bool Success { get; set; } /// /// 结果消息 /// public string Message { get; set; } /// /// 隐藏的项目数量 /// public int HiddenCount { get; set; } /// /// 模型总项目数量 /// public int TotalCount { get; set; } /// /// 错误信息列表 /// public List Errors { get; set; } = new List(); } /// /// 可见性统计信息 /// public class VisibilityStatistics { /// /// 模型总项目数量 /// public int TotalModelItems { get; set; } /// /// 具有物流分类的项目数量 /// public int LogisticsItems { get; set; } /// /// 没有物流分类的项目数量 /// public int NonLogisticsItems { get; set; } /// /// 当前隐藏的项目数量 /// public int HiddenItems { get; set; } /// /// 当前可见的项目数量 /// public int VisibleItems { get; set; } } /// /// 可见性管理器 /// 负责ModelItem可见性控制的核心业务逻辑 /// public class VisibilityManager { #region 私有字段 private readonly Document _document; private List _lastHiddenItems; // 缓存最后一次隐藏的项目列表 #endregion #region 事件 /// /// 进度报告事件 /// public event EventHandler ProgressChanged; /// /// 操作完成事件 /// public event EventHandler OperationCompleted; #endregion #region 构造函数 /// /// 初始化可见性管理器 /// public VisibilityManager() { _document = NavisApplication.ActiveDocument; _lastHiddenItems = new List(); } #endregion #region 静态方法 /// /// 检查ModelItem或其任何子项是否包含物流属性 /// /// 要检查的ModelItem /// 如果本身或任何子项包含物流属性则返回true private static bool HasLogisticsAttributesRecursive(ModelItem item) { // 首先检查当前项目 if (CategoryAttributeManager.HasLogisticsAttributes(item)) { return true; } // 然后递归检查子项目 if (item.Children != null && item.Children.Count() > 0) { foreach (ModelItem child in item.Children) { if (HasLogisticsAttributesRecursive(child)) { return true; } } } return false; } /// /// 静态方法:隐藏非物流分类项目 /// /// 操作结果 public static VisibilityOperationResult HideNonLogisticsItems() { try { var document = NavisApplication.ActiveDocument; if (document == null || document.Models.Count == 0) { return new VisibilityOperationResult { Success = true, Message = "没有加载的模型" }; } // 关键修复:在执行任何操作前,先将所有内容重置为可见,确保从一个已知的干净状态开始 document.Models.ResetAllHidden(); var rootItems = document.Models.SelectMany(model => model.RootItem.Children).ToList(); var itemsToHide = new List(); // 遍历所有顶层模型 foreach (var item in rootItems) { if (!HasLogisticsAttributesRecursive(item)) { itemsToHide.Add(item); } } // 创建一个集合来执行隐藏操作 var collectionToHide = new ModelItemCollection(); collectionToHide.AddRange(itemsToHide); if (collectionToHide.Count > 0) { document.Models.SetHidden(collectionToHide, true); } // 精确计算隐藏和总项目数 int totalItemsCount = rootItems.Sum(CountDescendantsAndSelf); var visibleRootItems = rootItems.Except(itemsToHide); int visibleItemsCount = visibleRootItems.Sum(CountDescendantsAndSelf); int hiddenCount = totalItemsCount - visibleItemsCount; return new VisibilityOperationResult { Success = true, Message = $"成功隐藏 {hiddenCount} 个非物流项目", HiddenCount = hiddenCount, TotalCount = totalItemsCount }; } catch (Exception ex) { return new VisibilityOperationResult { Success = false, Message = $"操作失败: {ex.Message}", HiddenCount = 0, TotalCount = 0, Errors = { ex.Message } }; } } /// /// 静态方法:显示所有项目 /// /// 操作结果 public static VisibilityOperationResult ShowAllItems() { try { var document = NavisApplication.ActiveDocument; if (document == null || document.Models.Count == 0) { return new VisibilityOperationResult { Success = true, Message = "没有加载的模型" }; } // 使用 ResetAllHidden 确保所有项目都被显示 document.Models.ResetAllHidden(); var rootItems = document.Models.SelectMany(model => model.RootItem.Children).ToList(); int totalItemsCount = rootItems.Sum(CountDescendantsAndSelf); return new VisibilityOperationResult { Success = true, Message = "所有项目已显示", HiddenCount = 0, // 重置后,隐藏数量必为0 TotalCount = totalItemsCount }; } catch (Exception ex) { return new VisibilityOperationResult { Success = false, Message = $"显示操作失败: {ex.Message}", HiddenCount = 0, TotalCount = 0, Errors = { ex.Message } }; } } /// /// 静态方法:根据物流类型显示特定项目 /// /// 要显示的物流元素类型 /// 操作结果 public static VisibilityOperationResult ShowLogisticsItemsOnly(CategoryAttributeManager.LogisticsElementType elementType) { try { var document = NavisApplication.ActiveDocument; var allItems = GetAllModelItemsStatic(); var itemsToHide = new List(); foreach (var item in allItems) { string typeValue = CategoryAttributeManager.GetLogisticsPropertyValue(item, CategoryAttributeManager.LogisticsProperties.TYPE); if (typeValue != elementType.ToString() && !string.IsNullOrEmpty(typeValue)) { itemsToHide.Add(item); } } // 首先显示所有项目 document.Models.ResetAllHidden(); // 然后隐藏非目标类型的项目 if (itemsToHide.Count > 0) { var collection = new ModelItemCollection(); foreach (var item in itemsToHide) { collection.Add(item); } document.Models.SetHidden(collection, true); } return new VisibilityOperationResult { Success = true, Message = $"仅显示 {elementType} 类型的项目,隐藏了 {itemsToHide.Count} 个其他项目", HiddenCount = itemsToHide.Count, TotalCount = allItems.Count }; } catch (Exception ex) { return new VisibilityOperationResult { Success = false, Message = $"操作失败: {ex.Message}", HiddenCount = 0, TotalCount = 0, Errors = { ex.Message } }; } } /// /// 静态方法:获取模型中的所有ModelItem /// /// ModelItem列表 private static List GetAllModelItemsStatic() { var collection = new List(); var doc = NavisApplication.ActiveDocument; if (doc != null) { foreach (var model in doc.Models) { // 从根模型的子项开始收集,以避免包含不可见的根节点 foreach (var item in model.RootItem.Children) { CollectModelItemsStatic(item, collection); } } } return collection; } /// /// 静态方法:递归收集ModelItem及其所有子项 /// /// 当前ModelItem /// 收集列表 private static void CollectModelItemsStatic(ModelItem item, List collection) { collection.Add(item); foreach (ModelItem child in item.Children) { CollectModelItemsStatic(child, collection); } } /// /// 递归计算一个模型项及其所有后代的总数 /// /// 要计算的模型项 /// 总数 private static int CountDescendantsAndSelf(ModelItem item) { var items = new List(); CollectModelItemsStatic(item, items); return items.Count; } #endregion #region 实例方法 /// /// 异步隐藏非物流分类项目 /// public void HideNonLogisticsItemsAsync() { BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.WorkerSupportsCancellation = true; worker.DoWork += (sender, e) => { try { var allItems = GetAllModelItems(); var itemsToHide = new List(); for (int i = 0; i < allItems.Count; i++) { if (worker.CancellationPending) { e.Cancel = true; break; } if (!CategoryAttributeManager.HasLogisticsAttributes(allItems[i])) { itemsToHide.Add(allItems[i]); } // 报告进度 int progress = (i * 100) / allItems.Count; worker.ReportProgress(progress); } e.Result = new VisibilityOperationResult { Success = !e.Cancel, HiddenCount = itemsToHide.Count, TotalCount = allItems.Count, Message = e.Cancel ? "操作已取消" : $"成功隐藏 {itemsToHide.Count} 个非物流分类项目" }; // 缓存隐藏的项目列表 if (!e.Cancel) { _lastHiddenItems = itemsToHide; } } catch (Exception ex) { e.Result = new VisibilityOperationResult { Success = false, Message = $"操作失败: {ex.Message}", HiddenCount = 0, TotalCount = 0 }; } }; worker.ProgressChanged += (sender, e) => { ProgressChanged?.Invoke(this, e); }; worker.RunWorkerCompleted += (sender, e) => { var result = (VisibilityOperationResult)e.Result; if (result.Success && result.HiddenCount > 0) { // 执行隐藏操作 try { var collection = new ModelItemCollection(); foreach (var item in _lastHiddenItems) { collection.Add(item); } _document.Models.SetHidden(collection, true); } catch (Exception ex) { result.Success = false; result.Message = $"隐藏操作失败: {ex.Message}"; result.Errors.Add(ex.Message); } } OperationCompleted?.Invoke(this, result); }; worker.RunWorkerAsync(); } /// /// 实例方法:同步隐藏非物流分类项目(用于小型模型) /// /// 操作结果 public VisibilityOperationResult HideNonLogisticsItemsInstance() { try { var allItems = GetAllModelItems(); var itemsToHide = new List(); foreach (var item in allItems) { if (!CategoryAttributeManager.HasLogisticsAttributes(item)) { itemsToHide.Add(item); } } if (itemsToHide.Count > 0) { var collection = new ModelItemCollection(); foreach (var item in itemsToHide) { collection.Add(item); } _document.Models.SetHidden(collection, true); _lastHiddenItems = itemsToHide; } return new VisibilityOperationResult { Success = true, Message = $"成功隐藏 {itemsToHide.Count} 个非物流分类项目", HiddenCount = itemsToHide.Count, TotalCount = allItems.Count }; } catch (Exception ex) { return new VisibilityOperationResult { Success = false, Message = $"操作失败: {ex.Message}", HiddenCount = 0, TotalCount = 0, Errors = { ex.Message } }; } } /// /// 实例方法:显示所有项目 /// /// 操作结果 public VisibilityOperationResult ShowAllItemsInstance() { try { _document.Models.ResetAllHidden(); var totalCount = GetAllModelItems().Count; _lastHiddenItems.Clear(); return new VisibilityOperationResult { Success = true, Message = "所有项目已显示", HiddenCount = 0, TotalCount = totalCount }; } catch (Exception ex) { return new VisibilityOperationResult { Success = false, Message = $"显示操作失败: {ex.Message}", HiddenCount = _lastHiddenItems.Count, TotalCount = 0, Errors = { ex.Message } }; } } /// /// 获取当前可见性统计信息 /// /// 可见性统计信息 public VisibilityStatistics GetCurrentStatistics() { try { var allItems = GetAllModelItems(); var logisticsCount = 0; foreach (var item in allItems) { if (CategoryAttributeManager.HasLogisticsAttributes(item)) { logisticsCount++; } } return new VisibilityStatistics { TotalModelItems = allItems.Count, LogisticsItems = logisticsCount, NonLogisticsItems = allItems.Count - logisticsCount, HiddenItems = _lastHiddenItems.Count, VisibleItems = allItems.Count - _lastHiddenItems.Count }; } catch (Exception) { // 异常情况返回空统计 return new VisibilityStatistics(); } } #endregion #region 私有方法 /// /// 获取模型中的所有ModelItem /// /// ModelItem列表 private List GetAllModelItems() { var allItems = new List(); try { // 遍历所有根级ModelItem foreach (ModelItem rootItem in _document.Models.RootItems) { CollectModelItems(rootItem, allItems); } } catch (Exception) { // 如果遍历失败,返回空列表 return new List(); } return allItems; } /// /// 递归收集ModelItem及其所有子项 /// /// 当前ModelItem /// 收集列表 private void CollectModelItems(ModelItem item, List collection) { if (item == null) return; // 添加当前项目 collection.Add(item); // 递归添加子项目 if (item.Children != null && item.Children.Count() > 0) { foreach (ModelItem child in item.Children) { CollectModelItems(child, collection); } } } #endregion } }