NavisworksTransport/src/UI/WPF/ViewModels/LayerManagementViewModel.cs

3711 lines
147 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 System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using NavisworksTransport.UI.WPF.Collections;
using NavisworksTransport.UI.WPF.Models;
using NavisworksTransport.UI.WPF.Commands;
using Autodesk.Navisworks.Api;
using NavisApplication = Autodesk.Navisworks.Api.Application;
using NavisworksTransport.Utils;
using NavisworksTransport.Core;
namespace NavisworksTransport.UI.WPF.ViewModels
{
/// <summary>
/// 分层管理页签的ViewModel - UI架构重构完成版本
///
/// 重构要点:
/// 1. 移除了ExecuteWithUIStateManagerAsync包装器该方法导致UIStateManager嵌套调用和死锁
/// 2. 实现正确的业务逻辑与UI分离模式
/// - 初始UI状态更新
/// - 纯业务逻辑执行后台线程不使用UIStateManager
/// - 结果UI更新
/// - 异常处理和UI更新
/// - 清理UI状态
/// 3. 确保Command的ExecuteAsync在Task.Run中执行避免嵌套UIStateManager调用
/// 4. 所有业务方法都遵循统一的四步骤模式,确保线程安全和避免死锁
/// 5. 特别针对PreviewSplitAsync方法进行了重点重构解决了死锁问题的根源
/// </summary>
public class LayerManagementViewModel : ViewModelBase, IDisposable
{
#region
private readonly FloorDetector _floorDetector;
private readonly FloorAttributeManager _floorAttributeManager = new FloorAttributeManager();
private readonly ModelSplitterManager _modelSplitterManager;
private readonly AttributeGrouper _attributeGrouper;
private readonly UIStateManager _uiStateManager;
private CancellationTokenSource _cancellationTokenSource;
// 选择事件订阅管理器
private SelectionEventSubscription _selectionEventSubscription;
// 资源释放状态标志
private bool _disposed;
#endregion
#region
private bool _isProcessing;
private bool _needsManualFloorSetup;
private bool _showPreviewResults;
private bool _showPreviewPrompt = true;
private string _floorAnalysisResult = "点击[分析楼层]开始检测";
private Brush _floorAnalysisResultColor = Brushes.Gray;
private string _selectedFloorAttribute;
private string _selectedNodesText = "未选择节点";
private string _floorAttributeStatus = "";
private string _outputDirectory = "";
private string _currentSelectionText = "未选择项目";
private string _currentOperationText = "";
private double _progressPercentage;
private string _selectedSplitStrategy = "智能检测";
private string _selectedCustomLayerOption = "按楼层";
private bool _showCustomLayerOptions = false;
private bool _includeChildNodes = true;
private bool _preserveMaterials = true;
private bool _generatePreview = false;
// 深度控制相关字段
private string _selectedDepth = "1级";
// 导出选项相关字段
private bool _embedXrefs = false;
private bool _preventObjectPropertyExport = false;
// 楼层属性相关字段
private string _selectedModelsText = "请在主界面中选择需要设置的模型";
private string _selectedFloorLevel = "F1";
private string _selectedZone = "";
private string _selectedSubSystem = "";
// 新的分层参数系统相关字段
private string _selectedLayerParameter = "楼层";
private string _selectedParameterValue = "F1";
private bool _showLayerAttributeInfo = false;
private string _currentLayerAttributeInfo = string.Empty;
private bool _showFloorAttributeInfo = false;
private string _currentFloorAttributeInfo = "";
private bool _showCancelButton = false;
#endregion
#region - 使线SetProperty方法
/// <summary>
/// 是否正在处理中
/// </summary>
public bool IsProcessing
{
get => _isProcessing;
set
{
if (SetPropertyThreadSafe(ref _isProcessing, value))
{
OnPropertyChanged(nameof(IsNotProcessing));
RefreshAllCommands();
}
}
}
/// <summary>
/// 是否未在处理中
/// </summary>
public bool IsNotProcessing => !IsProcessing;
/// <summary>
/// 楼层分析结果文本
/// </summary>
public string FloorAnalysisResult
{
get => _floorAnalysisResult;
set => SetPropertyThreadSafe(ref _floorAnalysisResult, value);
}
/// <summary>
/// 楼层分析结果颜色
/// </summary>
public Brush FloorAnalysisResultColor
{
get => _floorAnalysisResultColor;
set => SetPropertyThreadSafe(ref _floorAnalysisResultColor, value);
}
/// <summary>
/// 是否需要手动设置楼层
/// </summary>
public bool NeedsManualFloorSetup
{
get => _needsManualFloorSetup;
set => SetPropertyThreadSafe(ref _needsManualFloorSetup, value);
}
/// <summary>
/// 可用属性列表 - 使用线程安全集合
/// </summary>
public ThreadSafeObservableCollection<string> AvailableAttributes { get; } =
new ThreadSafeObservableCollection<string>();
/// <summary>
/// 选中的楼层属性
/// </summary>
public string SelectedFloorAttribute
{
get => _selectedFloorAttribute;
set
{
if (SetPropertyThreadSafe(ref _selectedFloorAttribute, value))
{
OnPropertyChanged(nameof(CanApplyFloorAttributes));
}
}
}
/// <summary>
/// 选中节点文本
/// </summary>
public string SelectedNodesText
{
get => _selectedNodesText;
set => SetPropertyThreadSafe(ref _selectedNodesText, value);
}
/// <summary>
/// 楼层属性设置状态
/// </summary>
public string FloorAttributeStatus
{
get => _floorAttributeStatus;
set => SetPropertyThreadSafe(ref _floorAttributeStatus, value);
}
/// <summary>
/// 是否可以应用楼层属性
/// </summary>
public bool CanApplyFloorAttributes =>
!string.IsNullOrEmpty(SelectedFloorAttribute) &&
!IsProcessing &&
SelectedNodesText != "未选择节点";
/// <summary>
/// 深度选项列表 - 使用线程安全集合
/// </summary>
public ThreadSafeObservableCollection<string> DepthOptions { get; } =
new ThreadSafeObservableCollection<string>
{
"1级",
"2级",
"3级",
"4级",
"5级",
"全部"
};
/// <summary>
/// 选中的遍历深度
/// </summary>
public string SelectedDepth
{
get => _selectedDepth;
set => SetPropertyThreadSafe(ref _selectedDepth, value);
}
/// <summary>
/// 获取当前选择的深度对应的数值
/// </summary>
public int CurrentDepthValue
{
get
{
switch (SelectedDepth)
{
case "1级":
return 1;
case "2级":
return 2;
case "3级":
return 3;
case "4级":
return 4;
case "5级":
return 5;
case "全部":
return 1000;
default:
return 1;
}
}
}
/// <summary>
/// 分层策略列表 - 使用线程安全集合
/// </summary>
public ThreadSafeObservableCollection<string> SplitStrategies { get; } =
new ThreadSafeObservableCollection<string>
{
"智能检测",
"自定义"
};
/// <summary>
/// 选中的分层策略
/// </summary>
public string SelectedSplitStrategy
{
get => _selectedSplitStrategy;
set
{
if (SetPropertyThreadSafe(ref _selectedSplitStrategy, value))
{
// 当选择"自定义"时显示二级选项
ShowCustomLayerOptions = value == "自定义";
OnPropertyChanged(nameof(CanPreviewSplit));
OnPropertyChanged(nameof(CanExecuteSplit));
OnPropertyChanged(nameof(CanIsolateSelectedLayer));
}
}
}
/// <summary>
/// 自定义分层选项集合
/// </summary>
public ThreadSafeObservableCollection<string> CustomLayerOptions { get; } =
new ThreadSafeObservableCollection<string>
{
"按楼层",
"按区域",
"按子系统"
};
/// <summary>
/// 选中的自定义分层选项
/// </summary>
public string SelectedCustomLayerOption
{
get => _selectedCustomLayerOption;
set
{
if (SetPropertyThreadSafe(ref _selectedCustomLayerOption, value))
{
OnPropertyChanged(nameof(CanPreviewSplit));
OnPropertyChanged(nameof(CanExecuteSplit));
OnPropertyChanged(nameof(CanIsolateSelectedLayer));
}
}
}
/// <summary>
/// 是否显示自定义分层选项
/// </summary>
public bool ShowCustomLayerOptions
{
get => _showCustomLayerOptions;
set => SetPropertyThreadSafe(ref _showCustomLayerOptions, value);
}
/// <summary>
/// 输出目录
/// </summary>
public string OutputDirectory
{
get => _outputDirectory;
set
{
if (SetPropertyThreadSafe(ref _outputDirectory, value))
{
OnPropertyChanged(nameof(CanPreviewSplit));
OnPropertyChanged(nameof(CanExecuteSplit));
OnPropertyChanged(nameof(CanIsolateSelectedLayer));
}
}
}
/// <summary>
/// 是否可以预览分层
/// </summary>
public bool CanPreviewSplit =>
!string.IsNullOrEmpty(SelectedSplitStrategy) &&
!IsProcessing;
/// <summary>
/// 是否可以执行分层不再依赖OutputDirectory改为使用文件对话框
/// </summary>
public bool CanExecuteSplit =>
SplitPreviewResults.Count > 0 &&
!IsProcessing;
/// <summary>
/// 是否可以单独显示选中的分层
/// </summary>
public bool CanIsolateSelectedLayer =>
SelectedPreviewResult != null &&
SplitPreviewResults.Count > 0 &&
!IsProcessing;
/// <summary>
/// 分层预览结果 - 使用线程安全集合
/// </summary>
public ThreadSafeObservableCollection<SplitPreviewItem> SplitPreviewResults { get; } =
new ThreadSafeObservableCollection<SplitPreviewItem>();
/// <summary>
/// 选中的预览结果
/// </summary>
private SplitPreviewItem _selectedPreviewResult;
public SplitPreviewItem SelectedPreviewResult
{
get => _selectedPreviewResult;
set
{
if (SetPropertyThreadSafe(ref _selectedPreviewResult, value))
{
OnPropertyChanged(nameof(CanIsolateSelectedLayer));
}
}
}
/// <summary>
/// 是否显示预览结果
/// </summary>
public bool ShowPreviewResults
{
get => _showPreviewResults;
set => SetPropertyThreadSafe(ref _showPreviewResults, value);
}
/// <summary>
/// 是否显示预览提示
/// </summary>
public bool ShowPreviewPrompt
{
get => _showPreviewPrompt;
set => SetPropertyThreadSafe(ref _showPreviewPrompt, value);
}
/// <summary>
/// 当前选择文本
/// </summary>
public string CurrentSelectionText
{
get => _currentSelectionText;
set
{
if (SetPropertyThreadSafe(ref _currentSelectionText, value))
{
OnPropertyChanged(nameof(HasSelectedItems));
OnPropertyChanged(nameof(CanSetLayerAttribute));
OnPropertyChanged(nameof(CanClearLayerAttribute));
}
}
}
/// <summary>
/// 是否有选中项目
/// </summary>
public bool HasSelectedItems => CurrentSelectionText != "未选择项目" && !IsProcessing;
/// <summary>
/// 包含子节点
/// </summary>
public bool IncludeChildNodes
{
get => _includeChildNodes;
set => SetPropertyThreadSafe(ref _includeChildNodes, value);
}
/// <summary>
/// 保留材质贴图
/// </summary>
public bool PreserveMaterials
{
get => _preserveMaterials;
set => SetPropertyThreadSafe(ref _preserveMaterials, value);
}
/// <summary>
/// 生成预览图
/// </summary>
public bool GeneratePreview
{
get => _generatePreview;
set => SetPropertyThreadSafe(ref _generatePreview, value);
}
/// <summary>
/// 嵌入 ReCap 和纹理数据
/// </summary>
public bool EmbedXrefs
{
get => _embedXrefs;
set => SetPropertyThreadSafe(ref _embedXrefs, value);
}
/// <summary>
/// 阻止导出对象特性
/// </summary>
public bool PreventObjectPropertyExport
{
get => _preventObjectPropertyExport;
set => SetPropertyThreadSafe(ref _preventObjectPropertyExport, value);
}
/// <summary>
/// 当前操作文本
/// </summary>
public string CurrentOperationText
{
get => _currentOperationText;
set => SetPropertyThreadSafe(ref _currentOperationText, value);
}
/// <summary>
/// 进度百分比
/// </summary>
public double ProgressPercentage
{
get => _progressPercentage;
set => SetPropertyThreadSafe(ref _progressPercentage, value);
}
/// <summary>
/// 选中模型文本
/// </summary>
public string SelectedModelsText
{
get => _selectedModelsText;
set => SetPropertyThreadSafe(ref _selectedModelsText, value);
}
/// <summary>
/// 选中的楼层标识
/// </summary>
public string SelectedFloorLevel
{
get => _selectedFloorLevel;
set => SetPropertyThreadSafe(ref _selectedFloorLevel, value);
}
/// <summary>
/// 选中的区域标识
/// </summary>
public string SelectedZone
{
get => _selectedZone;
set => SetPropertyThreadSafe(ref _selectedZone, value);
}
/// <summary>
/// 选中的子系统标识
/// </summary>
public string SelectedSubSystem
{
get => _selectedSubSystem;
set => SetPropertyThreadSafe(ref _selectedSubSystem, value);
}
/// <summary>
/// 选中的分层参数类型(楼层、区域、子系统)
/// </summary>
public string SelectedLayerParameter
{
get => _selectedLayerParameter;
set
{
if (SetPropertyThreadSafe(ref _selectedLayerParameter, value))
{
// 当分层参数类型改变时,自动更新参数值为合适的默认值
switch (value)
{
case "楼层":
SelectedParameterValue = "F1";
break;
case "区域":
SelectedParameterValue = "北区";
break;
case "子系统":
SelectedParameterValue = "消防系统";
break;
default:
SelectedParameterValue = "F1";
break;
}
// 通知相关属性更新
OnPropertyChanged(nameof(CanSetLayerAttribute));
}
}
}
/// <summary>
/// 分层参数值
/// </summary>
public string SelectedParameterValue
{
get => _selectedParameterValue;
set
{
if (SetPropertyThreadSafe(ref _selectedParameterValue, value))
{
// 通知相关属性更新
OnPropertyChanged(nameof(CanSetLayerAttribute));
}
}
}
/// <summary>
/// 是否显示分层属性信息
/// </summary>
public bool ShowLayerAttributeInfo
{
get => _showLayerAttributeInfo;
set => SetPropertyThreadSafe(ref _showLayerAttributeInfo, value);
}
/// <summary>
/// 当前分层属性信息
/// </summary>
public string CurrentLayerAttributeInfo
{
get => _currentLayerAttributeInfo;
set => SetPropertyThreadSafe(ref _currentLayerAttributeInfo, value);
}
/// <summary>
/// 分层参数选项集合
/// </summary>
public ObservableCollection<string> LayerParameterOptions { get; } = new ObservableCollection<string>
{
"楼层",
"区域",
"子系统"
};
/// <summary>
/// 是否显示楼层属性信息
/// </summary>
public bool ShowFloorAttributeInfo
{
get => _showFloorAttributeInfo;
set => SetPropertyThreadSafe(ref _showFloorAttributeInfo, value);
}
/// <summary>
/// 当前楼层属性信息
/// </summary>
public string CurrentFloorAttributeInfo
{
get => _currentFloorAttributeInfo;
set => SetPropertyThreadSafe(ref _currentFloorAttributeInfo, value);
}
/// <summary>
/// 是否有选中的模型(用于楼层属性设置)
/// </summary>
public bool HasSelectedModels
{
get
{
try
{
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
return document?.CurrentSelection?.SelectedItems?.Count > 0;
}
catch
{
return false;
}
}
}
/// <summary>
/// 是否可以设置楼层属性
/// </summary>
public bool CanSetFloorAttribute
{
get => HasSelectedModels && !string.IsNullOrEmpty(SelectedFloorLevel) && IsNotProcessing;
}
/// <summary>
/// 是否可以设置分层属性
/// </summary>
public bool CanSetLayerAttribute => IsNotProcessing && !string.IsNullOrWhiteSpace(SelectedParameterValue) && HasSelectedItems;
/// <summary>
/// 是否可以清除分层属性
/// </summary>
public bool CanClearLayerAttribute
{
get
{
try
{
if (IsProcessing || !HasSelectedItems)
return false;
// 检查选中的模型是否有任何分层属性
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems?.Count > 0)
{
var selection = document.CurrentSelection.SelectedItems;
foreach (var item in selection)
{
// 使用新的快速检查方法
if (_floorAttributeManager.HasFloorAttributes(item))
{
return true;
}
}
}
return false;
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 检查清除分层属性条件异常: {ex.Message}", ex);
return false;
}
}
}
/// <summary>
/// 是否可以清除楼层属性
/// </summary>
public bool CanClearFloorAttribute
{
get
{
try
{
if (IsProcessing || !HasSelectedItems)
return false;
// 检查选中的模型是否有楼层属性
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems?.Count > 0)
{
var selection = document.CurrentSelection.SelectedItems;
foreach (var item in selection)
{
// 使用新的 Native API 方法
var floorLevel = _floorAttributeManager.GetFloorProperty(item, "楼层");
if (!string.IsNullOrEmpty(floorLevel))
{
return true;
}
}
}
return false;
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 检查清除楼层属性条件异常: {ex.Message}", ex);
return false;
}
}
}
/// <summary>
/// 是否显示取消按钮
/// </summary>
public bool ShowCancelButton
{
get => _showCancelButton;
set => SetPropertyThreadSafe(ref _showCancelButton, value);
}
#endregion
#region - 使Command Pattern
public ICommand AnalyzeFloorsCommand { get; private set; }
public ICommand RefreshAttributesCommand { get; private set; }
public ICommand SelectNodesCommand { get; private set; }
public ICommand ApplyFloorAttributesCommand { get; private set; }
public ICommand PreviewSplitCommand { get; private set; }
public ICommand ExecuteSplitCommand { get; private set; }
public ICommand BrowseOutputDirectoryCommand { get; private set; }
public ICommand SaveSelectedItemsCommand { get; private set; }
public ICommand CancelOperationCommand { get; private set; }
public ICommand DiagnosticCommand { get; private set; }
public ICommand TestExportToNwdCommand { get; private set; }
// 楼层属性相关命令
public ICommand RefreshSelectionCommand { get; private set; }
public ICommand SetFloorAttributeCommand { get; private set; }
public ICommand ClearFloorAttributeCommand { get; private set; }
public ICommand ViewFloorAttributeCommand { get; private set; }
// 新的分层属性命令
public ICommand SetLayerAttributeCommand { get; private set; }
public ICommand ClearLayerAttributeCommand { get; private set; }
public ICommand ViewLayerAttributeCommand { get; private set; }
// 单独显示相关命令
public ICommand IsolateSelectedLayerCommand { get; private set; }
public ICommand ShowAllLayersCommand { get; private set; }
#endregion
#region - 使
public LayerManagementViewModel() : base()
{
try
{
// 获取UI状态管理器实例
_uiStateManager = UIStateManager.Instance;
// 验证关键组件是否正常初始化
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
// 初始化业务逻辑组件
_floorDetector = new FloorDetector();
_modelSplitterManager = new ModelSplitterManager();
_attributeGrouper = new AttributeGrouper();
// 初始化命令 - 使用异步Command Pattern
InitializeCommands();
// 订阅事件
_modelSplitterManager.ProgressChanged += OnProgressChanged;
_modelSplitterManager.StatusChanged += OnStatusChanged;
// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
SubscribeToSelectionEvents();
// 异步初始化
InitializeAsync();
LogManager.Info("LayerManagementViewModel构造函数执行完成 - 使用统一UI架构");
}
catch (Exception ex)
{
LogManager.Error($"LayerManagementViewModel构造函数异常: {ex.Message}", ex);
// 在构造函数中尽量保证对象处于可用状态
CurrentOperationText = "初始化失败,请检查日志";
throw;
}
}
/// <summary>
/// 构造函数 - 支持统一状态栏
/// </summary>
/// <param name="mainViewModel">主ViewModel用于统一状态栏</param>
public LayerManagementViewModel(LogisticsControlViewModel mainViewModel) : base()
{
try
{
// 设置主ViewModel引用到基类
SetMainViewModel(mainViewModel);
// 获取UI状态管理器实例
_uiStateManager = UIStateManager.Instance;
// 验证关键组件是否正常初始化
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
// 初始化业务逻辑组件
_floorDetector = new FloorDetector();
_modelSplitterManager = new ModelSplitterManager();
_attributeGrouper = new AttributeGrouper();
// 初始化命令 - 使用异步Command Pattern
InitializeCommands();
// 订阅事件
_modelSplitterManager.ProgressChanged += OnProgressChanged;
_modelSplitterManager.StatusChanged += OnStatusChanged;
// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
SubscribeToSelectionEvents();
// 异步初始化
InitializeAsync();
LogManager.Info("LayerManagementViewModel构造函数执行完成 - 支持统一状态栏");
}
catch (Exception ex)
{
LogManager.Error($"LayerManagementViewModel构造函数异常: {ex.Message}", ex);
// 在构造函数中尽量保证对象处于可用状态
CurrentOperationText = "初始化失败,请检查日志";
throw;
}
}
#endregion
#region - Command Pattern
/// <summary>
/// 初始化命令使用Command Pattern框架
/// </summary>
private void InitializeCommands()
{
SafeExecute(() =>
{
// 使用异步RelayCommand采用正确的业务逻辑与UI分离模式
AnalyzeFloorsCommand = new RelayCommand(
async () => await AnalyzeFloorsAsync(),
() => IsNotProcessing);
RefreshAttributesCommand = new RelayCommand(
async () => await RefreshAttributesAsync(),
() => IsNotProcessing);
SelectNodesCommand = new RelayCommand(
async () => await SelectNodesAsync(),
() => IsNotProcessing);
ApplyFloorAttributesCommand = new RelayCommand(
async () => await ApplyFloorAttributesAsync(),
() => CanApplyFloorAttributes);
PreviewSplitCommand = new RelayCommand(
async () => await PreviewSplitAsync(),
() => CanPreviewSplit);
ExecuteSplitCommand = new RelayCommand(
async () => await ExecuteSplitAsync(),
() => CanExecuteSplit);
BrowseOutputDirectoryCommand = new RelayCommand(
async () => await BrowseOutputDirectoryAsync(),
() => IsNotProcessing);
SaveSelectedItemsCommand = new RelayCommand(
async () => await SaveSelectedItemsAsync(),
() => HasSelectedItems);
CancelOperationCommand = new RelayCommand(CancelOperation, () => IsProcessing);
DiagnosticCommand = new RelayCommand(
async () => await RunDiagnosticAsync(),
() => IsNotProcessing);
TestExportToNwdCommand = new RelayCommand(
async () => await TestExportToNwdAsync(),
() => IsNotProcessing);
// 楼层属性相关命令初始化
RefreshSelectionCommand = new RelayCommand(
async () => await RefreshSelectionAsync(),
() => IsNotProcessing);
SetFloorAttributeCommand = new RelayCommand(
async () => await SetFloorAttributeAsync(),
() => CanSetFloorAttribute);
ClearFloorAttributeCommand = new RelayCommand(
async () => await ClearFloorAttributeAsync(),
() => CanClearFloorAttribute);
ViewFloorAttributeCommand = new RelayCommand(
async () => await ViewFloorAttributeAsync(),
() => HasSelectedItems);
// 新的分层属性命令初始化
SetLayerAttributeCommand = new RelayCommand(
async () => await SetLayerAttributeAsync(),
() => CanSetLayerAttribute);
ClearLayerAttributeCommand = new RelayCommand(
async () => await ClearLayerAttributeAsync(),
() => CanClearLayerAttribute);
ViewLayerAttributeCommand = new RelayCommand(
async () => await ViewLayerAttributeAsync(),
() => HasSelectedItems);
// 单独显示相关命令
IsolateSelectedLayerCommand = new RelayCommand(
async () => await IsolateSelectedLayerAsync(),
() => CanIsolateSelectedLayer);
ShowAllLayersCommand = new RelayCommand(
async () => await ShowAllLayersAsync(),
() => IsNotProcessing);
LogManager.Info("分层管理命令初始化完成");
}, "初始化命令");
}
#endregion
#region - 使UIStateManager
// ExecuteWithUIStateManagerAsync包装器已移除 - 该方法导致UIStateManager嵌套调用和死锁
// 现在采用正确的业务逻辑与UI分离模式
/// <summary>
/// 分析楼层 - 实现正确的业务逻辑与UI分离模式
/// </summary>
private async Task AnalyzeFloorsAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
ShowCancelButton = false; // 分析楼层操作不支持取消
CurrentOperationText = "正在分析楼层...";
UpdateMainStatus("检测模型中的楼层属性", -1, true);
});
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var command = new FloorAnalysisCommand(_floorDetector, CurrentDepthValue);
var result = await command.ExecuteAsync();
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (result.IsSuccess)
{
SetFloorAnalysisResult(result.Message, result.StatusColor);
NeedsManualFloorSetup = result.NeedsManualSetup;
UpdateMainStatus("楼层分析完成");
}
else
{
SetFloorAnalysisResult(result.ErrorMessage, Brushes.Red);
UpdateMainStatus("楼层分析失败");
}
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 分析楼层异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SetFloorAnalysisResult($"分析失败: {ex.Message}", Brushes.Red);
UpdateMainStatus("操作异常");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
ShowCancelButton = false;
CurrentOperationText = "";
ProgressPercentage = 0;
});
}
}
/// <summary>
/// 刷新属性列表 - 实现正确的业务逻辑与UI分离模式
/// </summary>
private async Task RefreshAttributesAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
CurrentOperationText = "正在刷新属性列表...";
UpdateMainStatus("获取模型属性");
});
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var command = new RefreshAttributesCommand(_floorDetector, CurrentDepthValue);
var result = await command.ExecuteAsync();
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AvailableAttributes.Clear();
if (result.IsSuccess && result.Attributes != null)
{
foreach (var attr in result.Attributes)
{
AvailableAttributes.Add(attr);
}
UpdateMainStatus($"成功获取 {result.Attributes.Count} 个属性");
}
else
{
UpdateMainStatus(result.ErrorMessage ?? "获取属性失败");
}
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 刷新属性异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
AvailableAttributes.Clear();
UpdateMainStatus($"刷新失败: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
CurrentOperationText = "";
});
}
}
/// <summary>
/// 选择节点 - 实现正确的业务逻辑与UI分离模式
/// </summary>
private async Task SelectNodesAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
CurrentOperationText = "正在获取选中节点...";
UpdateMainStatus("检查当前选择");
});
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var command = new SelectNodesCommand();
var result = await command.ExecuteAsync();
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (result.IsSuccess)
{
SelectedNodesText = NavisworksSelectionHelper.FormatSelectionText(result.Count, result.SelectedItems, "个节点");
UpdateMainStatus(result.Count > 0
? $"获取到 {result.Count} 个选中节点"
: "当前没有选中的节点");
}
else
{
SelectedNodesText = "获取节点失败";
UpdateMainStatus(result.ErrorMessage ?? "选择节点操作失败");
}
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 选择节点异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedNodesText = "获取节点异常";
UpdateMainStatus($"操作失败: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
CurrentOperationText = "";
});
}
}
/// <summary>
/// 应用楼层属性 - 实现正确的业务逻辑与UI分离模式
/// </summary>
private async Task ApplyFloorAttributesAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
CurrentOperationText = "正在应用楼层属性...";
FloorAttributeStatus = "处理中...";
UpdateMainStatus("为选中节点设置楼层属性");
});
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var command = new ApplyFloorAttributesCommand(SelectedFloorAttribute);
var result = await command.ExecuteAsync();
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (result.IsSuccess)
{
FloorAttributeStatus = $"成功为 {result.Count} 个节点设置楼层属性";
UpdateMainStatus($"属性设置完成,影响 {result.Count} 个节点");
}
else
{
FloorAttributeStatus = result.ErrorMessage ?? "楼层属性设置失败";
UpdateMainStatus("属性设置操作失败");
}
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 应用楼层属性异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
FloorAttributeStatus = $"设置失败: {ex.Message}";
UpdateMainStatus("属性设置异常");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
CurrentOperationText = "";
});
}
}
/// <summary>
/// 预览分层 - 实现正确的业务逻辑与UI分离模式解决死锁问题的关键方法
/// </summary>
private async Task PreviewSplitAsync()
{
// 1. 初始UI状态更新 - 清空旧结果并显示加载状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
ShowCancelButton = false; // 预览操作不支持取消
CurrentOperationText = "正在生成分层预览...";
ProgressPercentage = 0;
UpdateMainStatus("准备分层配置");
// 清空旧的预览结果
SplitPreviewResults.Clear();
// 显示加载状态
ShowPreviewResults = false;
ShowPreviewPrompt = false;
// 添加加载提示项
var loadingItem = new SplitPreviewItem
{
LayerName = "正在分析...",
LayerAttribute = "分析中"
};
SplitPreviewResults.Add(loadingItem);
ShowPreviewResults = true;
});
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var strategy = GetSplitStrategyFromString(SelectedSplitStrategy);
var config = new ModelSplitterManager.SplitConfiguration
{
Strategy = strategy,
OutputDirectory = OutputDirectory,
MaxDepth = CurrentDepthValue, // 传递深度参数
ExportOptions = new ModelSplitterManager.NwdExportUserOptions
{
EmbedXrefs = EmbedXrefs,
PreventObjectPropertyExport = PreventObjectPropertyExport,
FileVersion = "2026"
}
};
LogManager.Info($"[LayerManagementViewModel] 开始预览分层,策略: {SelectedSplitStrategy}");
var command = new PreviewSplitCommand(_modelSplitterManager, config);
var result = await command.ExecuteAsync();
LogManager.Info($"[LayerManagementViewModel] 预览分层完成,成功: {result.IsSuccess}, 项目数: {result.PreviewItems?.Count ?? 0}");
// 3. 结果UI更新 - 清空加载提示并显示实际结果
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 清空加载提示
SplitPreviewResults.Clear();
if (result.IsSuccess && result.PreviewItems?.Count > 0)
{
// 添加实际预览结果
foreach (var item in result.PreviewItems)
{
SplitPreviewResults.Add(item);
}
ShowPreviewResults = true;
ShowPreviewPrompt = false;
UpdateMainStatus($"预览完成:共检测到 {SplitPreviewResults.Count} 个分层(智能遍历仅显示关键节点)");
}
else
{
// 预览失败或无结果,不在列表中显示错误项,而是隐藏结果列表并显示提示
ShowPreviewResults = false;
ShowPreviewPrompt = true; // 显示提示信息
UpdateMainStatus(result.ErrorMessage ?? "未找到任何分层属性,请先设置模型的分层属性(楼层、区域或子系统)");
}
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 预览分层异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 清空加载提示,隐藏结果列表并显示异常提示
SplitPreviewResults.Clear();
ShowPreviewResults = false;
ShowPreviewPrompt = true; // 显示提示信息
UpdateMainStatus($"预览异常: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
ShowCancelButton = false;
// 只有在预览成功时才清空操作文本,失败时保留提示信息
if (SplitPreviewResults.Count > 0)
{
CurrentOperationText = "";
}
ProgressPercentage = 0;
});
}
}
/// <summary>
/// 执行分层 - 使用文件对话框选择保存目录实现正确的业务逻辑与UI分离模式
/// </summary>
private async Task ExecuteSplitAsync()
{
try
{
// 首先在UI线程上使用文件对话框让用户选择保存目录
LogManager.Info("[LayerManagementViewModel] 准备显示文件选择对话框");
var browseCommand = new BrowseDirectoryCommand("");
var browseResult = await browseCommand.ExecuteAsync();
LogManager.Info($"[LayerManagementViewModel] 文件对话框结果: IsSuccess={browseResult?.IsSuccess}, Path={browseResult?.SelectedPath}");
if (browseResult == null || !browseResult.IsSuccess || string.IsNullOrEmpty(browseResult.SelectedPath))
{
// 用户取消了对话框或选择失败
LogManager.Info("[LayerManagementViewModel] 用户取消了分层保存操作");
return;
}
var selectedDirectory = browseResult.SelectedPath;
LogManager.Info($"[LayerManagementViewModel] 用户选择保存目录: {selectedDirectory}");
// 过滤出需要保存的分层
var layersToSave = SplitPreviewResults.Where(p => p.IsSelectedForSave).ToList();
if (layersToSave.Count == 0)
{
LogManager.Warning("[LayerManagementViewModel] 没有选中任何分层进行保存");
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "没有选中任何分层进行保存";
UpdateMainStatus("请勾选需要保存的分层");
});
return;
}
LogManager.Info($"[LayerManagementViewModel] 将保存 {layersToSave.Count}/{SplitPreviewResults.Count} 个选中的分层");
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
ShowCancelButton = true; // 分层保存支持取消
CurrentOperationText = "正在执行分层保存...";
UpdateMainStatus($"准备保存到: {selectedDirectory}");
});
_cancellationTokenSource = new CancellationTokenSource();
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var strategy = GetSplitStrategyFromString(SelectedSplitStrategy);
var config = new ModelSplitterManager.SplitConfiguration
{
Strategy = strategy,
OutputDirectory = selectedDirectory,
MaxDepth = CurrentDepthValue, // 传递深度参数
ExportOptions = new ModelSplitterManager.NwdExportUserOptions
{
EmbedXrefs = EmbedXrefs,
PreventObjectPropertyExport = PreventObjectPropertyExport,
FileVersion = "2026"
}
};
// 将选中的 SplitPreviewItem 转换为 SplitPreviewResult 以便传递给 ModelSplitterManager
var previewResultsForSave = layersToSave.Select(item => new ModelSplitterManager.SplitPreviewResult
{
LayerName = item.LayerName,
LayerAttribute = item.LayerAttribute,
Items = item.Items,
IsSelectedForSave = item.IsSelectedForSave,
Metadata = item.Metadata // 重要复制元数据包含RootNodes等优化信息
}).ToList();
LogManager.Info($"[LayerManagementViewModel] 开始执行分层,输出目录: {selectedDirectory}");
// 直接调用 ModelSplitterManager 的方法处理选中的分层
await ExecuteSelectedLayersAsync(config, previewResultsForSave, _cancellationTokenSource.Token);
LogManager.Info($"[LayerManagementViewModel] 分层执行完成");
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "分层保存完成";
UpdateMainStatus($"文件已保存到: {selectedDirectory}");
// 更新OutputDirectory显示可选
OutputDirectory = selectedDirectory;
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 执行分层异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "分层保存异常";
UpdateMainStatus($"保存失败: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
ShowCancelButton = false;
_cancellationTokenSource = null;
});
}
}
/// <summary>
/// 执行选中的分层保存
/// </summary>
private async Task ExecuteSelectedLayersAsync(
ModelSplitterManager.SplitConfiguration config,
List<ModelSplitterManager.SplitPreviewResult> previewResultsForSave,
CancellationToken cancellationToken)
{
Progress progress = null;
try
{
// 确保输出目录存在
if (!Directory.Exists(config.OutputDirectory))
{
Directory.CreateDirectory(config.OutputDirectory);
}
// 逐个处理选中的分层
int successCount = 0;
var failedLayers = new List<string>();
// 🎯 创建批量导出进度条(在主线程中)
await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
{
progress = NavisApplication.BeginProgress("批量导出分层",
$"准备导出 {previewResultsForSave.Count} 个分层...");
});
for (int i = 0; i < previewResultsForSave.Count; i++)
{
var preview = previewResultsForSave[i];
// 🎯 更新进度条描述和百分比(在主线程中)
bool userCanceled = false;
await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
{
if (progress != null && !progress.IsCanceled)
{
// 计算总体进度百分比
double currentProgress = (double)i / previewResultsForSave.Count;
progress.Update(currentProgress);
// 更新进度条描述
NavisApplication.EndProgress();
progress = NavisApplication.BeginProgress("批量导出分层",
$"正在导出第 {i + 1}/{previewResultsForSave.Count} 个分层:{preview.LayerName}");
}
else if (progress != null && progress.IsCanceled)
{
userCanceled = true;
}
});
// 检查用户是否取消或请求取消
if (userCanceled || cancellationToken.IsCancellationRequested)
{
LogManager.Info($"[LayerManagementViewModel] 用户取消分层操作,已处理 {successCount}/{previewResultsForSave.Count} 个分层");
break;
}
try
{
// 处理单个分层
await ProcessSingleLayerAsync(preview, config, cancellationToken);
successCount++;
LogManager.Info($"[LayerManagementViewModel] 分层 {preview.LayerName} 处理成功 ({successCount}/{previewResultsForSave.Count})");
}
catch (Exception layerEx)
{
string errorMsg = $"分层 {preview.LayerName} 处理失败: {layerEx.Message}";
LogManager.Error($"[LayerManagementViewModel] {errorMsg}");
failedLayers.Add(preview.LayerName);
}
}
// 生成最终统计信息
string finalMessage = $"分层处理完成:成功 {successCount} 个,失败 {failedLayers.Count} 个";
if (failedLayers.Count > 0)
{
finalMessage += $"\n失败列表: {string.Join(", ", failedLayers)}";
LogManager.Warning($"[LayerManagementViewModel] {finalMessage}");
}
else
{
LogManager.Info($"[LayerManagementViewModel] {finalMessage}");
}
// 只更新状态栏文字,不更新进度百分比
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus(finalMessage);
});
// 如果所有分层都失败,抛出异常
if (successCount == 0 && previewResultsForSave.Count > 0)
{
throw new InvalidOperationException($"所有选中的分层处理都失败了,共 {previewResultsForSave.Count} 个分层");
}
LogManager.Info($"[LayerManagementViewModel] 分层执行完成:成功 {successCount}/{previewResultsForSave.Count}");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 分层执行失败: {ex.Message}");
throw;
}
finally
{
// 🎯 确保进度条被关闭(在主线程中)
if (progress != null)
{
await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
{
try
{
NavisApplication.EndProgress();
LogManager.Info("[LayerManagementViewModel] 批量导出进度条已关闭");
}
catch (Exception progressEx)
{
LogManager.Error($"[LayerManagementViewModel] 关闭进度条失败: {progressEx.Message}");
}
});
}
}
}
/// <summary>
/// 处理单个分层(异步版本)
/// </summary>
private async Task ProcessSingleLayerAsync(ModelSplitterManager.SplitPreviewResult preview, ModelSplitterManager.SplitConfiguration config, CancellationToken cancellationToken)
{
try
{
LogManager.Info($"[LayerManagementViewModel] 开始处理分层: {preview.LayerName}, 类型: {preview.LayerAttribute}");
// 检查取消请求
cancellationToken.ThrowIfCancellationRequested();
if (preview.Items == null || preview.Items.Count == 0)
{
LogManager.Warning($"[LayerManagementViewModel] 分层 {preview.LayerName} 没有包含模型元素,跳过导出");
return;
}
// 生成输出文件路径(使用新的智能文件名格式)
string fileName = GenerateFileName(preview.LayerName, config.Strategy, config);
string outputPath = Path.Combine(config.OutputDirectory, fileName);
LogManager.Info($"[LayerManagementViewModel] 分层文件路径: {outputPath}");
// 检查模型项数量,对大量模型项进行特殊处理
if (preview.Items != null && preview.Items.Count > 100)
{
LogManager.Warning($"[LayerManagementViewModel] 大量模型项检测:{preview.Items.Count}个,可能需要更多内存和时间");
// 强制垃圾回收,释放内存
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
LogManager.Info($"[LayerManagementViewModel] 垃圾回收完成,当前内存: {GC.GetTotalMemory(false) / 1024 / 1024} MB");
}
// 使用TryExportToNwd API导出分层
bool success = ExportLayerToNwd(preview, outputPath, config);
if (success)
{
LogManager.Info($"[LayerManagementViewModel] 分层 {preview.LayerName} 导出成功: {outputPath}");
}
else
{
LogManager.Error($"[LayerManagementViewModel] 分层 {preview.LayerName} 导出失败");
throw new InvalidOperationException($"分层 {preview.LayerName} 导出失败");
}
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 处理分层失败 {preview.LayerName}: {ex.Message}");
throw;
}
}
/// <summary>
/// 获取根节点名称 - 新的智能文件名格式使用
/// 逻辑:文档文件名 → 第一个模型根项DisplayName → "NavisworksModel"
/// </summary>
/// <returns>根节点名称</returns>
private string GetRootNodeName()
{
try
{
var document = NavisApplication.ActiveDocument;
// 优先使用文档文件名(去除扩展名)
if (document != null && !string.IsNullOrEmpty(document.FileName))
{
string fileName = Path.GetFileNameWithoutExtension(document.FileName);
if (!string.IsNullOrEmpty(fileName))
{
return SanitizeFileName(fileName);
}
}
// 其次尝试使用第一个模型根项的DisplayName
if (document?.Models != null && document.Models.Count > 0)
{
foreach (Model model in document.Models)
{
if (model.RootItem != null && !string.IsNullOrEmpty(model.RootItem.DisplayName))
{
return SanitizeFileName(model.RootItem.DisplayName);
}
}
}
// 最后使用默认名称
return "NavisworksModel";
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 获取根节点名称失败: {ex.Message}");
return "NavisworksModel";
}
}
/// <summary>
/// 获取分层属性类型名称
/// </summary>
/// <param name="strategy">分层策略</param>
/// <returns>属性类型名称</returns>
private string GetAttributeTypeName(ModelSplitterManager.SplitStrategy strategy)
{
switch (strategy)
{
case ModelSplitterManager.SplitStrategy.BySmartFloorDetection:
return "楼层";
case ModelSplitterManager.SplitStrategy.ByFloorAttribute:
return "楼层";
case ModelSplitterManager.SplitStrategy.ByZoneAttribute:
return "区域";
case ModelSplitterManager.SplitStrategy.BySubSystemAttribute:
return "子系统";
default:
return "分层";
}
}
/// <summary>
/// 清理文件名中的非法字符
/// </summary>
/// <param name="fileName">原始文件名</param>
/// <returns>清理后的文件名</returns>
private string SanitizeFileName(string fileName)
{
if (string.IsNullOrEmpty(fileName))
return "未命名";
// 移除文件名中的非法字符,保留中文字符
var invalidChars = Path.GetInvalidFileNameChars();
string sanitized = fileName;
foreach (char c in invalidChars)
{
sanitized = sanitized.Replace(c, '_');
}
// 移除其他特殊字符,保留字母、数字、下划线和中文字符
sanitized = System.Text.RegularExpressions.Regex.Replace(sanitized, @"[^\w\u4e00-\u9fa5\-\.]", "_");
// 移除多余的下划线
sanitized = System.Text.RegularExpressions.Regex.Replace(sanitized, @"_{2,}", "_");
// 移除首尾下划线
sanitized = sanitized.Trim('_', ' ');
// 限制长度
if (sanitized.Length > 50)
{
sanitized = sanitized.Substring(0, 50).TrimEnd('_');
}
return string.IsNullOrEmpty(sanitized) ? "未命名" : sanitized;
}
/// <summary>
/// 生成文件名 - 新的智能格式根节点名称_分层属性_属性值_时间戳.nwd
/// </summary>
/// <param name="attributeValue">属性值(分层名称)</param>
/// <param name="strategy">分层策略</param>
/// <param name="config">配置信息</param>
/// <returns>文件名(不包括路径)</returns>
private string GenerateFileName(string attributeValue, ModelSplitterManager.SplitStrategy strategy, ModelSplitterManager.SplitConfiguration config)
{
try
{
// 获取根节点名称
string rootNodeName = GetRootNodeName();
// 获取分层属性类型名称
string attributeTypeName = GetAttributeTypeName(strategy);
// 清理属性值(原分层名称)
string sanitizedAttributeValue = SanitizeFileName(attributeValue);
// 生成时间戳
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
// 新的统一格式根节点名称_分层属性_属性值_时间戳.nwd
string fileName = $"{rootNodeName}_{attributeTypeName}_{sanitizedAttributeValue}_{timestamp}.nwd";
LogManager.Info($"[LayerManagementViewModel] 生成智能文件名: {fileName}");
LogManager.Info($"[LayerManagementViewModel] 文件名组成: 根节点='{rootNodeName}', 属性类型='{attributeTypeName}', 属性值='{sanitizedAttributeValue}', 时间戳='{timestamp}'");
return fileName;
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 生成智能文件名失败: {ex.Message}");
// 失败时使用后备命名方式
string fallbackName = $"NavisworksModel_分层_{SanitizeFileName(attributeValue)}_{DateTime.Now:yyyyMMdd_HHmmss}.nwd";
LogManager.Warning($"[LayerManagementViewModel] 使用后备文件名: {fallbackName}");
return fallbackName;
}
}
/// <summary>
/// 导出分层到NWD文件
/// </summary>
private bool ExportLayerToNwd(ModelSplitterManager.SplitPreviewResult preview, string outputPath, ModelSplitterManager.SplitConfiguration config)
{
try
{
// 委托给SimplifiedModelSplitterManager处理实际的导出逻辑
return _modelSplitterManager.ExportLayerToNwd(preview, outputPath, config);
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 导出分层失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 浏览输出目录 - 实现正确的业务逻辑与UI分离模式
/// </summary>
private async Task BrowseOutputDirectoryAsync()
{
try
{
// 浏览目录操作需要在UI线程执行但不需要显示Processing状态
var command = new BrowseDirectoryCommand(OutputDirectory);
var result = await command.ExecuteAsync();
// 结果UI更新
if (result.IsSuccess && !string.IsNullOrEmpty(result.SelectedPath))
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
OutputDirectory = result.SelectedPath;
});
LogManager.Info($"[分层管理] 用户选择目录: {result.SelectedPath}");
}
else if (!result.IsSuccess && !string.IsNullOrEmpty(result.ErrorMessage))
{
LogManager.Warning($"[分层管理] 目录选择失败: {result.ErrorMessage}");
}
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 浏览目录异常: {ex.Message}", ex);
}
}
/// <summary>
/// 保存选中项目
/// </summary>
private async Task SaveSelectedItemsAsync()
{
try
{
LogManager.Info("[LayerManagementViewModel] 开始保存当前选择项");
IsProcessing = true;
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.Models?.Count == 0 || document.CurrentSelection.SelectedItems.Count == 0)
{
LogManager.Warning("[LayerManagementViewModel] 没有活动文档或未选择节点");
MessageBox.Show("请先选择要保存的项目", "保存提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
// 保存当前选择状态
var originalSelection = new List<ModelItem>(document.CurrentSelection.SelectedItems);
LogManager.Info($"[LayerManagementViewModel] 用户选中了 {originalSelection.Count} 个节点");
// 生成默认文件名
string defaultFileName = GenerateDefaultFileNameForMultipleItems(document, originalSelection);
// 获取保存路径
string saveFilePath = null;
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
var saveDialog = new Microsoft.Win32.SaveFileDialog
{
Title = "保存当前选择项",
Filter = "Navisworks文件 (*.nwd)|*.nwd",
DefaultExt = "nwd",
FileName = defaultFileName
};
if (saveDialog.ShowDialog() == true)
{
saveFilePath = saveDialog.FileName;
}
});
if (string.IsNullOrEmpty(saveFilePath))
{
return;
}
bool exportResult = false;
string errorMessage = "";
// 在主线程执行导出
await Task.Run(() =>
{
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
try
{
// 收集要导出的项目 (仅根节点)
var itemsToExport = new ModelItemCollection();
itemsToExport.AddRange(originalSelection);
LogManager.Info($"[LayerManagementViewModel] 准备导出 {itemsToExport.Count} 个节点");
// 保存当前可见性状态
var originalVisibilityState = SaveCurrentVisibilityState(document);
try
{
// 隔离显示
bool isolateSuccess = VisibilityHelper.IsolateSpecificItems(itemsToExport);
if (!isolateSuccess) throw new InvalidOperationException("隔离显示失败");
// 导出选项
var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions
{
ExcludeHiddenItems = true,
EmbedXrefs = EmbedXrefs,
PreventObjectPropertyExport = PreventObjectPropertyExport
};
document.ExportToNwd(saveFilePath, exportOptions);
exportResult = true;
LogManager.Info("[LayerManagementViewModel] ExportToNwd API调用完成");
}
finally
{
// 恢复可见性
RestoreVisibilityState(document, originalVisibilityState);
}
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 导出异常: {ex.Message}", ex);
errorMessage = ex.Message;
exportResult = false;
}
});
});
// 恢复原始选择 (需要在主线程)
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
try
{
document.CurrentSelection.Clear();
document.CurrentSelection.AddRange(originalSelection);
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 恢复选择失败: {ex.Message}");
}
});
// 显示结果
if (exportResult)
{
if (File.Exists(saveFilePath))
{
var fileInfo = new FileInfo(saveFilePath);
MessageBox.Show(
$"保存成功!\n\n文件: {saveFilePath}\n大小: {fileInfo.Length / 1024} KB",
"保存结果", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
else
{
MessageBox.Show($"保存失败: {errorMessage}", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 保存选中项目过程异常: {ex.Message}", ex);
MessageBox.Show($"保存过程异常: {ex.Message}", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
IsProcessing = false;
}
}
/// <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>
/// 运行环境诊断 - 检查Navisworks API环境
/// </summary>
private async Task RunDiagnosticAsync()
{
try
{
LogManager.Info("[LayerManagementViewModel] 开始环境诊断");
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
CurrentOperationText = "正在进行环境诊断...";
UpdateMainStatus("检查Navisworks API环境和线程状态");
});
// 2. 纯业务逻辑执行(后台线程)
string diagnosticReport = await Task.Run(() =>
{
return CreateDiagnosticReport();
});
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "环境诊断完成";
UpdateMainStatus("环境诊断报告已生成");
});
// 显示诊断结果
ShowDiagnosticResult(diagnosticReport);
LogManager.Info("[LayerManagementViewModel] 环境诊断完成");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 环境诊断异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "环境诊断异常";
UpdateMainStatus($"诊断失败: {ex.Message}");
});
ShowDiagnosticResult($"诊断过程中发生异常: {ex.Message}");
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
/// <summary>
/// 创建环境诊断报告
/// </summary>
/// <returns>诊断报告</returns>
private string CreateDiagnosticReport()
{
var report = new System.Text.StringBuilder();
report.AppendLine("=== Navisworks API环境诊断报告 ===");
try
{
// 1. 线程状态
var apartmentState = System.Threading.Thread.CurrentThread.GetApartmentState();
report.AppendLine($"线程状态: {apartmentState} {(apartmentState == System.Threading.ApartmentState.STA ? "" : "")}");
// 2. API可用性
try
{
var app = Autodesk.Navisworks.Api.Application.ActiveDocument;
report.AppendLine("API可用性: 可用 ✓");
}
catch (Exception apiEx)
{
report.AppendLine($"API可用性: 异常 - {apiEx.Message} ✗");
}
// 3. 文档状态
try
{
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document != null)
{
report.AppendLine($"活动文档: {document.FileName ?? ""} ✓");
report.AppendLine($"模型数量: {document.Models?.Count ?? 0}");
}
else
{
report.AppendLine("活动文档: 无 ✗");
}
}
catch (Exception docEx)
{
report.AppendLine($"活动文档: 异常 - {docEx.Message} ✗");
}
// 4. 内存状态
long memoryMB = GC.GetTotalMemory(false) / 1024 / 1024;
report.AppendLine($"当前内存: {memoryMB} MB");
report.AppendLine("=== 诊断完成 ===");
string result = report.ToString();
LogManager.Info($"[LayerManagement] 环境诊断报告:\n{result}");
return result;
}
catch (Exception ex)
{
string error = $"诊断过程出错: {ex.Message}";
report.AppendLine(error);
LogManager.Error($"[LayerManagement] {error}");
return report.ToString();
}
}
/// <summary>
/// 显示环境诊断结果对话框
/// </summary>
private void ShowDiagnosticResult(string report)
{
try
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
var diagWindow = new Window
{
Title = "Navisworks API环境诊断",
Width = 600,
Height = 500,
WindowStartupLocation = WindowStartupLocation.CenterScreen,
ResizeMode = ResizeMode.CanResize
};
var textBox = new System.Windows.Controls.TextBox
{
Text = report,
IsReadOnly = true,
VerticalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Auto,
HorizontalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Auto,
FontFamily = new System.Windows.Media.FontFamily("Consolas"),
FontSize = 12,
Margin = new Thickness(10),
TextWrapping = TextWrapping.Wrap
};
var panel = new System.Windows.Controls.DockPanel();
var buttonPanel = new System.Windows.Controls.StackPanel
{
Orientation = System.Windows.Controls.Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(10)
};
System.Windows.Controls.DockPanel.SetDock(buttonPanel, System.Windows.Controls.Dock.Bottom);
var copyButton = new System.Windows.Controls.Button
{
Content = "复制报告",
Width = 80,
Height = 25,
Margin = new Thickness(0, 0, 10, 0)
};
copyButton.Click += (s, e) =>
{
try
{
System.Windows.Clipboard.SetText(report);
MessageBox.Show("诊断报告已复制到剪贴板", "复制成功", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
MessageBox.Show($"复制失败: {ex.Message}", "复制错误", MessageBoxButton.OK, MessageBoxImage.Warning);
}
};
var closeButton = new System.Windows.Controls.Button
{
Content = "关闭",
Width = 80,
Height = 25,
IsDefault = true
};
closeButton.Click += (s, e) => diagWindow.Close();
buttonPanel.Children.Add(copyButton);
buttonPanel.Children.Add(closeButton);
panel.Children.Add(buttonPanel);
panel.Children.Add(textBox);
diagWindow.Content = panel;
diagWindow.ShowDialog();
}));
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 显示诊断结果失败: {ex.Message}");
}
}
/// <summary>
/// 测试ExportToNwd API - 专门的导出API
/// </summary>
private async Task TestExportToNwdAsync()
{
try
{
LogManager.Info("[LayerManagementViewModel] 开始测试ExportToNwd API");
// 1. 简单状态更新
IsProcessing = true;
// 2. 获取保存路径
string saveFilePath = null;
System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
var saveDialog = new Microsoft.Win32.SaveFileDialog
{
Title = "复杂导出测试 - 选择保存位置",
Filter = "Navisworks文件 (*.nwd)|*.nwd",
DefaultExt = "nwd",
FileName = $"复杂导出测试_{DateTime.Now:yyyyMMdd_HHmmss}.nwd"
};
if (saveDialog.ShowDialog() == true)
{
saveFilePath = saveDialog.FileName;
}
});
if (string.IsNullOrEmpty(saveFilePath))
{
LogManager.Info("[LayerManagementViewModel] 用户取消了ExportToNwd测试");
return;
}
// 3. 使用ExportToNwd API测试
bool exportResult = false;
string errorMessage = "";
try
{
LogManager.Info($"[LayerManagementViewModel] 开始ExportToNwd测试到: {saveFilePath}");
// 获取当前文档
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.Models?.Count == 0)
{
errorMessage = "没有活动文档或模型";
exportResult = false;
}
else
{
// 保存当前选择状态
var originalSelection = new List<ModelItem>();
foreach (ModelItem item in document.CurrentSelection.SelectedItems)
{
originalSelection.Add(item);
}
try
{
// 复杂测试:基于用户当前选择的节点进行导出
ModelItem targetItem = null;
var allVisibilityItems = new List<ModelItem>();
// 第一步:检查用户当前是否有选中的节点
if (document.CurrentSelection.SelectedItems.Count > 0)
{
// 使用用户选中的第一个节点作为目标
targetItem = document.CurrentSelection.SelectedItems.First();
LogManager.Info($"[LayerManagementViewModel] 使用用户选中的节点: {targetItem.DisplayName}");
}
else
{
LogManager.Info("[LayerManagementViewModel] 用户没有选中节点,将自动选择一个二级节点");
}
// 第二步:收集所有可见的模型项(用于可见性控制)
foreach (Model model in document.Models)
{
var rootItem = model.RootItem;
LogManager.Info($"[LayerManagementViewModel] 处理模型根项: {rootItem.DisplayName},子项数量: {rootItem.Children.Count()}");
// 遍历一级节点
foreach (ModelItem firstLevel in rootItem.Children)
{
allVisibilityItems.Add(firstLevel); // 收集用于可见性控制
LogManager.Info($"[LayerManagementViewModel] 一级节点: {firstLevel.DisplayName},子项数量: {firstLevel.Children.Count()}");
// 如果用户没有选中节点则选择第一个二级节点作为fallback
if (targetItem == null && firstLevel.Children.Count() > 0)
{
foreach (ModelItem secondLevel in firstLevel.Children)
{
targetItem = secondLevel;
LogManager.Info($"[LayerManagementViewModel] 选中二级目标节点: {secondLevel.DisplayName}");
break; // 只要第一个二级节点
}
}
// 收集其他二级节点用于可见性控制
foreach (ModelItem secondLevel in firstLevel.Children)
{
allVisibilityItems.Add(secondLevel);
}
}
}
if (targetItem == null)
{
LogManager.Error("[LayerManagementViewModel] 没有找到可用的二级节点");
errorMessage = "没有找到可用的二级节点";
exportResult = false;
return;
}
// 第二步:确保目标节点被选中
if (!originalSelection.Contains(targetItem))
{
// 如果目标节点不在原始选择中,则清空并重新选择
document.CurrentSelection.Clear();
document.CurrentSelection.Add(targetItem);
LogManager.Info($"[LayerManagementViewModel] 已选择目标节点: {targetItem.DisplayName}");
}
else
{
LogManager.Info($"[LayerManagementViewModel] 目标节点已在选择中: {targetItem.DisplayName}");
}
// 第三步:隐藏其他节点,只保留目标节点可见
LogManager.Info($"[LayerManagementViewModel] 准备导出选中节点及其所有子项: {targetItem.DisplayName}");
LogManager.Info($"[LayerManagementViewModel] 目标节点子项数量: {targetItem.Children.Count()}");
// 创建要隐藏的项目集合 - 隐藏除了目标节点之外的所有一级节点
var itemsToHide = new ModelItemCollection();
int hiddenCount = 0;
foreach (ModelItem item in allVisibilityItems)
{
// 隐藏除了目标节点之外的所有一级节点
if (item != targetItem && item.Parent?.Parent == null) // 确保是一级节点
{
try
{
itemsToHide.Add(item);
hiddenCount++;
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 添加隐藏项目失败: {item.DisplayName} - {ex.Message}");
}
}
}
// 执行隐藏操作
if (itemsToHide.Count > 0)
{
try
{
document.Models.SetHidden(itemsToHide, true);
LogManager.Info($"[LayerManagementViewModel] 成功隐藏 {hiddenCount} 个一级节点,只保留目标节点可见");
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 隐藏操作失败: {ex.Message}");
}
}
// 确保选中目标节点
document.CurrentSelection.Clear();
document.CurrentSelection.Add(targetItem);
LogManager.Info($"[LayerManagementViewModel] 已选择目标节点: {targetItem.DisplayName}");
// 创建导出选项 - 使用用户配置的参数
var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions();
exportOptions.ExcludeHiddenItems = true; // 只导出可见项目(目标节点及其子项)
exportOptions.EmbedXrefs = EmbedXrefs;
exportOptions.PreventObjectPropertyExport = PreventObjectPropertyExport;
LogManager.Info($"[LayerManagementViewModel] TestExportToNwd导出选项: 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
{
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
{
document.CurrentSelection.Clear();
foreach (ModelItem item in originalSelection)
{
try
{
document.CurrentSelection.Add(item);
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] ExportToNwd恢复选择项时出错: {ex.Message}");
}
}
LogManager.Info("[LayerManagementViewModel] 已恢复原始选择");
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 恢复选择失败: {ex.Message}");
}
}
}
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] ExportToNwd API异常: {ex.Message}", ex);
errorMessage = ex.Message;
exportResult = false;
}
// 4. 显示结果
if (exportResult)
{
if (File.Exists(saveFilePath))
{
var fileInfo = new FileInfo(saveFilePath);
MessageBox.Show(
$"ExportToNwd API测试成功\n\n文件路径: {saveFilePath}\n文件大小: {fileInfo.Length / 1024} KB\n创建时间: {fileInfo.CreationTime}\n\n这证明ExportToNwd API工作正常",
"ExportToNwd测试结果", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
MessageBox.Show("ExportToNwd操作完成但文件不存在。", "ExportToNwd测试结果", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
else
{
MessageBox.Show($"ExportToNwd API测试失败\n\n错误信息: {errorMessage}\n\n这可能说明ExportToNwd API有问题。",
"ExportToNwd测试结果", MessageBoxButton.OK, MessageBoxImage.Error);
}
LogManager.Info("[LayerManagementViewModel] ExportToNwd API测试完成");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] ExportToNwd测试过程异常: {ex.Message}", ex);
MessageBox.Show($"ExportToNwd测试过程异常: {ex.Message}", "ExportToNwd测试错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
// 5. 简单的状态清理
IsProcessing = false;
}
}
private void CancelOperation()
{
_cancellationTokenSource?.Cancel();
}
#endregion
// 选择状态格式化方法已移至NavisworksSelectionHelper中
#region
/// <summary>
/// 更新当前选择状态 - 使用新的选择管理服务
/// </summary>
public async Task UpdateCurrentSelectionAsync()
{
try
{
// 使用新的选择管理服务获取选择状态(后台线程)
var selectionResult = await NavisworksSelectionHelper.GetCurrentSelectionStateAsync();
// 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (selectionResult.Success)
{
CurrentSelectionText = NavisworksSelectionHelper.FormatSelectionText(selectionResult, "个项目");
}
else
{
CurrentSelectionText = selectionResult.ErrorMessage ?? "获取选择状态失败";
LogManager.Warning($"[LayerManagementViewModel] 更新选择状态失败: {selectionResult.ErrorMessage}");
}
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 更新选择状态异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentSelectionText = "选择状态异常";
});
}
}
/// <summary>
/// 异步初始化
/// </summary>
private async void InitializeAsync()
{
try
{
// 设置默认输出目录
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
OutputDirectory = Path.Combine(documentsPath, "NavisworksTransport", "分层输出");
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 初始化失败: {ex.Message}");
}
}
private void OnProgressChanged(object sender, ProgressChangedEventArgs e)
{
// 使用UIStateManager安全更新进度
_uiStateManager.QueueUIUpdate(() =>
{
ProgressPercentage = e.ProgressPercentage;
UpdateMainStatus(e.UserState?.ToString() ?? "");
}, UIUpdatePriority.Normal);
}
private void OnStatusChanged(object sender, string status)
{
_uiStateManager.QueueUIUpdate(() =>
{
CurrentOperationText = status ?? "处理中...";
}, UIUpdatePriority.Normal);
}
private void SetFloorAnalysisResult(string text, Brush color)
{
FloorAnalysisResult = text;
FloorAnalysisResultColor = color;
}
private ModelSplitterManager.SplitStrategy GetSplitStrategyFromString(string strategy)
{
switch (strategy)
{
case "智能检测":
return ModelSplitterManager.SplitStrategy.BySmartFloorDetection;
case "自定义":
// 根据二级选项决定具体的自定义分层策略
switch (SelectedCustomLayerOption)
{
case "按楼层":
return ModelSplitterManager.SplitStrategy.ByFloorAttribute;
case "按区域":
return ModelSplitterManager.SplitStrategy.ByZoneAttribute;
case "按子系统":
return ModelSplitterManager.SplitStrategy.BySubSystemAttribute;
default:
return ModelSplitterManager.SplitStrategy.ByFloorAttribute;
}
default:
return ModelSplitterManager.SplitStrategy.BySmartFloorDetection;
}
}
/// <summary>
/// 获取当前选择的完整分层策略描述(包含二级选项)
/// </summary>
public string GetFullStrategyDescription()
{
if (SelectedSplitStrategy == "自定义" && !string.IsNullOrEmpty(SelectedCustomLayerOption))
{
return $"{SelectedSplitStrategy} - {SelectedCustomLayerOption}";
}
return SelectedSplitStrategy;
}
/// <summary>
/// 生成针对多个选中项目的默认文件名
/// </summary>
private string GenerateDefaultFileNameForMultipleItems(Document document, List<ModelItem> selectedItems)
{
try
{
// 获取根节点名(第一个模型的名称,去掉扩展名)
string rootName = "Unknown";
if (document.Models.Count > 0)
{
var firstModel = document.Models.First();
if (!string.IsNullOrEmpty(firstModel.FileName))
{
rootName = Path.GetFileNameWithoutExtension(firstModel.FileName);
}
else if (!string.IsNullOrEmpty(firstModel.RootItem.DisplayName))
{
rootName = firstModel.RootItem.DisplayName;
}
}
// 生成选中项目描述
string selectedDescription;
if (selectedItems.Count == 1)
{
selectedDescription = selectedItems[0].DisplayName ?? "Unknown";
}
else
{
selectedDescription = $"{selectedItems.Count}个节点";
}
// 清理文件名中的非法字符
string cleanRootName = CleanFileName(rootName);
string cleanSelectedDescription = CleanFileName(selectedDescription);
// 生成时间戳
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
// 组合文件名
return $"{cleanRootName}_{cleanSelectedDescription}_{timestamp}.nwd";
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 生成多选文件名失败: {ex.Message}");
return $"多选集_{DateTime.Now:yyyyMMdd_HHmmss}.nwd";
}
}
/// <summary>
/// 生成默认文件名根节点名_选中节点名_时间戳
/// </summary>
private string GenerateDefaultFileName(Document document, ModelItem selectedItem)
{
try
{
// 获取根节点名(第一个模型的名称,去掉扩展名)
string rootName = "Unknown";
if (document.Models.Count > 0)
{
var firstModel = document.Models.First();
if (!string.IsNullOrEmpty(firstModel.FileName))
{
rootName = Path.GetFileNameWithoutExtension(firstModel.FileName);
}
else if (!string.IsNullOrEmpty(firstModel.RootItem.DisplayName))
{
rootName = firstModel.RootItem.DisplayName;
}
}
// 获取选中节点名,清理特殊字符
string selectedName = "Unknown";
if (selectedItem != null && !string.IsNullOrEmpty(selectedItem.DisplayName))
{
selectedName = selectedItem.DisplayName;
}
// 清理文件名中的非法字符
string cleanRootName = CleanFileName(rootName);
string cleanSelectedName = CleanFileName(selectedName);
// 生成时间戳
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
// 组合文件名
return $"{cleanRootName}_{cleanSelectedName}_{timestamp}.nwd";
}
catch (Exception ex)
{
LogManager.Warning($"[LayerManagementViewModel] 生成默认文件名失败: {ex.Message}");
return $"选择集_{DateTime.Now:yyyyMMdd_HHmmss}.nwd";
}
}
/// <summary>
/// 清理文件名中的非法字符
/// </summary>
private string CleanFileName(string fileName)
{
if (string.IsNullOrEmpty(fileName))
return "Unknown";
// Windows文件名非法字符
char[] invalidChars = Path.GetInvalidFileNameChars();
string cleanName = fileName;
foreach (char c in invalidChars)
{
cleanName = cleanName.Replace(c, '_');
}
// 替换一些常见的特殊字符
cleanName = cleanName.Replace(" ", "_")
.Replace(".", "_")
.Replace(":", "_")
.Replace("/", "_")
.Replace("\\", "_");
// 限制长度
if (cleanName.Length > 50)
{
cleanName = cleanName.Substring(0, 50);
}
return cleanName;
}
private void RefreshAllCommands()
{
OnPropertyChanged(nameof(CanApplyFloorAttributes));
OnPropertyChanged(nameof(CanPreviewSplit));
OnPropertyChanged(nameof(CanExecuteSplit));
OnPropertyChanged(nameof(CanIsolateSelectedLayer));
OnPropertyChanged(nameof(HasSelectedItems));
OnPropertyChanged(nameof(CanSetFloorAttribute));
OnPropertyChanged(nameof(CanClearFloorAttribute));
OnPropertyChanged(nameof(CanSetLayerAttribute));
OnPropertyChanged(nameof(CanClearLayerAttribute));
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 释放资源的具体实现
/// </summary>
/// <param name="disposing">是否正在释放托管资源</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
try
{
// 取消正在进行的操作
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
// 取消事件订阅
if (_modelSplitterManager != null)
{
_modelSplitterManager.ProgressChanged -= OnProgressChanged;
_modelSplitterManager.StatusChanged -= OnStatusChanged;
}
// 取消Navisworks选择变化事件订阅
UnsubscribeFromSelectionEvents();
LogManager.Info("[LayerManagementViewModel] 资源清理完成");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 资源清理失败: {ex.Message}");
}
}
_disposed = true;
}
}
#endregion
#region
/// <summary>
/// 向后兼容提供UIStateManager访问接口
/// </summary>
public UIStateManager UIStateManager => _uiStateManager;
/// <summary>
/// 验证ViewModel状态是否正常
/// </summary>
public bool IsValidState()
{
return _uiStateManager != null &&
AvailableAttributes != null &&
SplitPreviewResults != null &&
SplitStrategies != null;
}
/// <summary>
/// 获取ViewModel状态信息
/// </summary>
public string GetStateInfo()
{
return $"UIStateManager: {(_uiStateManager != null ? "" : "")}, " +
$"可用属性数量: {AvailableAttributes?.Count ?? 0}, " +
$"预览结果数量: {SplitPreviewResults?.Count ?? 0}";
}
#endregion
#region
/// <summary>
/// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
/// </summary>
private void SubscribeToSelectionEvents()
{
try
{
// 使用新的选择管理服务订阅选择变化事件
_selectionEventSubscription = NavisworksSelectionHelper.SubscribeToSelectionChanges(
OnSelectionChangedAsync, _uiStateManager);
LogManager.Info("[LayerManagementViewModel] 已通过NavisworksSelectionHelper订阅选择变化事件");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 订阅选择事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅Navisworks选择变化事件 - 使用新的选择管理服务
/// </summary>
private void UnsubscribeFromSelectionEvents()
{
try
{
// 通过Dispose方法取消订阅
_selectionEventSubscription?.Dispose();
_selectionEventSubscription = null;
LogManager.Info("[LayerManagementViewModel] 已通过NavisworksSelectionHelper取消订阅选择变化事件");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 取消选择事件订阅失败: {ex.Message}", ex);
}
}
/// <summary>
/// 选择变化事件处理器 - 使用新的选择管理服务
/// </summary>
private async Task OnSelectionChangedAsync(SelectionStateResult selectionResult)
{
// 如果已经释放,直接返回
if (_disposed) return;
try
{
// 更新楼层属性相关的选择状态(使用新的选择结果)
await UpdateFloorAttributeSelectionStateAsync(selectionResult);
LogManager.Info($"[LayerManagementViewModel] 选择状态已更新: {selectionResult.Count}个项目");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 处理选择变化事件异常: {ex.Message}", ex);
}
}
/// <summary>
/// 更新楼层属性相关的选择状态 - 使用新的选择管理服务
/// </summary>
private async Task UpdateFloorAttributeSelectionStateAsync(SelectionStateResult selectionResult = null)
{
// 如果已经释放,直接返回
if (_disposed) return;
try
{
// 如果没有提供选择结果,则获取当前选择状态
if (selectionResult == null)
{
selectionResult = await NavisworksSelectionHelper.GetCurrentSelectionStateAsync();
}
// UI更新 - 使用新的选择管理服务格式化选择文本
if (selectionResult.Success)
{
SelectedModelsText = NavisworksSelectionHelper.FormatSelectionText(selectionResult, "个模型");
}
else
{
SelectedModelsText = selectionResult.ErrorMessage ?? "检查选择状态异常";
}
// 刷新命令状态
OnPropertyChanged(nameof(HasSelectedItems));
OnPropertyChanged(nameof(HasSelectedModels));
OnPropertyChanged(nameof(CanSetFloorAttribute));
OnPropertyChanged(nameof(CanClearFloorAttribute));
LogManager.Info($"[LayerManagementViewModel] 楼层属性选择状态已更新: 成功={selectionResult.Success}, 数量={selectionResult.Count}");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 更新楼层属性选择状态异常: {ex.Message}", ex);
SelectedModelsText = "检查选择状态异常";
}
}
#endregion
#region
/// <summary>
/// 刷新选择状态 - 使用新的选择管理服务
/// </summary>
private async Task RefreshSelectionAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
CurrentOperationText = "正在检查模型选择...";
});
try
{
// 2. 使用新的选择管理服务获取选择状态(后台线程)
var selectionResult = await NavisworksSelectionHelper.GetCurrentSelectionStateAsync();
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (selectionResult.Success)
{
SelectedModelsText = NavisworksSelectionHelper.FormatSelectionText(selectionResult, "个模型");
CurrentOperationText = "检查完成";
}
else
{
SelectedModelsText = selectionResult.ErrorMessage ?? "检查选择状态失败";
CurrentOperationText = "检查失败";
}
// 刷新命令状态
OnPropertyChanged(nameof(HasSelectedItems));
OnPropertyChanged(nameof(HasSelectedModels));
OnPropertyChanged(nameof(CanSetFloorAttribute));
OnPropertyChanged(nameof(CanClearFloorAttribute));
});
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 刷新选择异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedModelsText = "检查选择状态异常";
CurrentOperationText = $"检查失败: {ex.Message}";
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
/// <summary>
/// 设置楼层属性
/// </summary>
private async Task SetFloorAttributeAsync()
{
await SafeExecuteAsync(async () =>
{
IsProcessing = true;
ShowCancelButton = false; // 设置楼层属性不支持取消
CurrentOperationText = "正在设置楼层属性...";
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems == null || document.CurrentSelection.SelectedItems.Count == 0)
{
CurrentOperationText = "未选择任何模型项";
return;
}
// 使用成员变量 _floorAttributeManager
var selectedItems = document.CurrentSelection.SelectedItems.ToList();
var successCount = 0;
foreach (var item in selectedItems)
{
try
{
bool result = _floorAttributeManager.SetFloorAttribute(
item,
SelectedFloorLevel,
string.IsNullOrWhiteSpace(SelectedZone) ? null : SelectedZone,
string.IsNullOrWhiteSpace(SelectedSubSystem) ? null : SelectedSubSystem);
if (result)
{
successCount++;
}
}
catch (Exception ex)
{
LogManager.Error($"设置模型 {item.DisplayName} 的楼层属性失败:{ex.Message}");
}
}
CurrentOperationText = $"楼层属性设置完成,成功设置 {successCount}/{selectedItems.Count} 个模型项";
LogManager.Info($"[LayerManagementViewModel] 楼层属性设置完成,成功 {successCount}/{selectedItems.Count} 个");
// 刷新选中模型信息
await RefreshSelectionAsync();
}, "设置楼层属性");
}
/// <summary>
/// 清除楼层属性 - 实现正确的业务逻辑与UI分离模式参考ModelSettingsViewModel
/// </summary>
private async Task ClearFloorAttributeAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
ShowCancelButton = false; // 清除楼层属性不支持取消
CurrentOperationText = "正在清除楼层属性...";
UpdateMainStatus("正在清除选中模型的楼层属性");
});
try
{
// 2. 纯业务逻辑执行后台线程不使用UIStateManager
var result = await Task.Run<dynamic>(() =>
{
try
{
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems == null || document.CurrentSelection.SelectedItems.Count == 0)
{
return new { Success = false, Count = 0, Message = "请先选择模型元素" };
}
// 使用成员变量 _floorAttributeManager
var selectedItems = document.CurrentSelection.SelectedItems.ToList();
var successCount = 0;
foreach (var item in selectedItems)
{
try
{
bool itemResult = _floorAttributeManager.ClearFloorAttribute(item);
if (itemResult)
{
successCount++;
}
}
catch (Exception itemEx)
{
LogManager.Warning($"清除模型项 {item.DisplayName} 的楼层属性失败:{itemEx.Message}");
}
}
return new
{
Success = successCount > 0,
Count = successCount,
TotalCount = selectedItems.Count,
Message = successCount > 0 ?
$"已清除 {successCount} 个模型项的楼层属性" :
"没有找到可清除的楼层属性"
};
}
catch (Exception ex)
{
return new { Success = false, Count = 0, TotalCount = 0, Message = $"清除属性失败: {ex.Message}" };
}
});
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = result.Message;
UpdateMainStatus(result.Success ?
$"楼层属性清除完成,成功清除 {result.Count}/{result.TotalCount} 个模型项" :
"楼层属性清除失败");
if (result.Success)
{
// 清除成功,刷新选择状态
LogManager.Info($"[LayerManagementViewModel] 清除楼层属性成功,{result.Count}/{result.TotalCount} 个模型项");
}
else
{
LogManager.Warning($"[LayerManagementViewModel] 清除楼层属性失败:{result.Message}");
}
});
// 4. 刷新选择状态
if (result.Success)
{
await RefreshSelectionAsync();
}
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 清除楼层属性异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "清除楼层属性异常";
UpdateMainStatus($"清除失败: {ex.Message}");
});
}
finally
{
// 5. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
ShowCancelButton = false;
});
}
}
/// <summary>
/// 查看楼専属性 - 不显示进度条的即时操作
/// </summary>
private async Task ViewFloorAttributeAsync()
{
try
{
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems == null || document.CurrentSelection.SelectedItems.Count == 0)
{
// 使用UI线程更新状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
ShowFloorAttributeInfo = true;
CurrentFloorAttributeInfo = "未选择任何模型项,请先选择要查看的模型";
});
return;
}
// 在后台线程执行业务逻辑
var result = await Task.Run<dynamic>(() =>
{
try
{
var selectedItems = document.CurrentSelection.SelectedItems.ToList();
var floorAttributeInfo = new List<string>();
foreach (var item in selectedItems.Take(10)) // 限制显示前10个避免信息过多
{
try
{
string floorLevel = _floorAttributeManager.GetFloorProperty(item, "楼层");
string itemName = item.DisplayName ?? "未命名";
if (!string.IsNullOrEmpty(floorLevel))
{
floorAttributeInfo.Add($"✅ {itemName}: {floorLevel}");
}
else
{
floorAttributeInfo.Add($"❌ {itemName}: 未设置楼层属性");
}
}
catch (Exception ex)
{
floorAttributeInfo.Add($"⚠️ {item.DisplayName}: 查询失败 - {ex.Message}");
}
}
if (selectedItems.Count > 10)
{
floorAttributeInfo.Add($"... 还有 {selectedItems.Count - 10} 个模型项未显示");
}
return new { Success = true, Info = string.Join("\n", floorAttributeInfo), Count = selectedItems.Count };
}
catch (Exception ex)
{
return new { Success = false, Info = $"查询失败: {ex.Message}", Count = 0 };
}
});
// 在UI线程更新结果
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentFloorAttributeInfo = result.Info;
ShowFloorAttributeInfo = true;
});
LogManager.Info($"[LayerManagementViewModel] 楼层属性查看完成,共 {result.Count} 个模型项");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 查看楼层属性异常: {ex.Message}", ex);
// 在UI线程显示错误信息
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentFloorAttributeInfo = $"查看操作异常: {ex.Message}";
ShowFloorAttributeInfo = true;
});
}
}
/// <summary>
/// 设置分层属性
/// </summary>
private async Task SetLayerAttributeAsync()
{
await SafeExecuteAsync(async () =>
{
if (string.IsNullOrWhiteSpace(SelectedParameterValue))
{
CurrentOperationText = "请输入参数值";
return;
}
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems?.Count == 0)
{
CurrentOperationText = "请先选择要设置属性的模型对象";
return;
}
IsProcessing = true;
ShowCancelButton = false;
CurrentOperationText = "正在设置分层属性...";
var totalItems = document.CurrentSelection.SelectedItems.Count;
var processedItems = 0;
try
{
// 使用成员变量 _floorAttributeManager
var selectedItems = document.CurrentSelection.SelectedItems.ToList();
foreach (var item in selectedItems)
{
// 使用新的SetSingleLayerAttribute方法只设置指定的属性类型
bool result = _floorAttributeManager.SetSingleLayerAttribute(item, SelectedLayerParameter, SelectedParameterValue);
if (result)
{
processedItems++;
}
ProgressPercentage = (double)processedItems / totalItems * 100;
}
CurrentOperationText = $"分层属性设置完成,成功设置 {processedItems}/{totalItems} 个对象的{SelectedLayerParameter}属性:{SelectedParameterValue}";
LogManager.Info($"[LayerManagementViewModel] 成功设置分层属性: {SelectedLayerParameter}={SelectedParameterValue},影响对象数:{processedItems}");
// 刷新选中模型信息
await RefreshSelectionAsync();
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 设置分层属性异常: {ex.Message}", ex);
CurrentOperationText = $"设置分层属性时发生错误:{ex.Message}";
}
finally
{
IsProcessing = false;
ProgressPercentage = 0;
}
}, "设置分层属性");
}
/// <summary>
/// 清除分层属性
/// </summary>
private async Task ClearLayerAttributeAsync()
{
await SafeExecuteAsync(async () =>
{
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems?.Count == 0)
{
CurrentOperationText = "请先选择要清除属性的模型对象";
return;
}
IsProcessing = true;
ShowCancelButton = false;
CurrentOperationText = "正在清除分层属性...";
var totalItems = document.CurrentSelection.SelectedItems.Count;
var processedItems = 0;
try
{
// 使用成员变量 _floorAttributeManager
var selectedItems = document.CurrentSelection.SelectedItems.ToList();
foreach (var item in selectedItems)
{
try
{
bool result = _floorAttributeManager.ClearFloorAttribute(item);
if (result)
{
processedItems++;
}
}
catch (Exception ex)
{
LogManager.Error($"清除模型 {item.DisplayName} 的分层属性失败:{ex.Message}");
}
ProgressPercentage = (double)(processedItems + 1) / totalItems * 100;
}
CurrentOperationText = $"分层属性清除完成,成功清除 {processedItems}/{totalItems} 个对象的分层属性";
LogManager.Info($"[LayerManagementViewModel] 成功清除分层属性,影响对象数:{processedItems}");
// 刷新选中模型信息
await RefreshSelectionAsync();
ShowLayerAttributeInfo = false;
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 清除分层属性异常: {ex.Message}", ex);
CurrentOperationText = $"清除分层属性时发生错误:{ex.Message}";
}
finally
{
IsProcessing = false;
ProgressPercentage = 0;
}
}, "清除分层属性");
}
/// <summary>
/// 查看分层属性
/// </summary>
private async Task ViewLayerAttributeAsync()
{
try
{
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems == null || document.CurrentSelection.SelectedItems.Count == 0)
{
// 使用UI线程更新状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
ShowLayerAttributeInfo = true;
CurrentLayerAttributeInfo = "未选择任何模型项,请先选择要查看的模型";
});
return;
}
// 在后台线程执行业务逻辑
var result = await Task.Run<dynamic>(() =>
{
try
{
var selectedItems = document.CurrentSelection.SelectedItems.ToList();
var totalItems = selectedItems.Count;
var attributeInfo = new System.Text.StringBuilder();
attributeInfo.AppendLine($"选中对象总数:{totalItems}");
attributeInfo.AppendLine();
var hasAttributeCount = 0;
foreach (var item in selectedItems.Take(30)) // 增加显示数量到30个
{
try
{
string itemName = item.DisplayName ?? "未命名";
var itemAttributes = new List<string>();
// 获取楼层属性
var floorLevel = _floorAttributeManager.GetFloorProperty(item, "楼层");
if (!string.IsNullOrEmpty(floorLevel))
{
itemAttributes.Add($"楼层={floorLevel}");
}
// 获取区域属性
var zone = _floorAttributeManager.GetFloorProperty(item, "区域");
if (!string.IsNullOrEmpty(zone))
{
itemAttributes.Add($"区域={zone}");
}
// 获取子系统属性
var subsystem = _floorAttributeManager.GetFloorProperty(item, "子系统");
if (!string.IsNullOrEmpty(subsystem))
{
itemAttributes.Add($"子系统={subsystem}");
}
if (itemAttributes.Count > 0)
{
hasAttributeCount++;
attributeInfo.AppendLine($"✅ {itemName}: {string.Join(", ", itemAttributes)}");
}
else
{
attributeInfo.AppendLine($"❌ {itemName}: 无分层属性");
}
}
catch (Exception ex)
{
attributeInfo.AppendLine($"⚠️ {item.DisplayName}: 查询失败 - {ex.Message}");
}
}
if (selectedItems.Count > 30)
{
attributeInfo.AppendLine($"... 还有 {selectedItems.Count - 30} 个模型项未显示");
}
return new { Success = true, Info = attributeInfo.ToString(), Count = totalItems, HasAttributeCount = hasAttributeCount };
}
catch (Exception ex)
{
return new { Success = false, Info = $"查询失败: {ex.Message}", Count = 0, HasAttributeCount = 0 };
}
});
// 在UI线程更新结果
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentLayerAttributeInfo = result.Info;
ShowLayerAttributeInfo = true;
});
LogManager.Info($"[LayerManagementViewModel] 分层属性查看完成,共 {result.Count} 个模型项,其中 {result.HasAttributeCount} 个有分层属性");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 查看分层属性异常: {ex.Message}", ex);
// 在UI线程显示错误信息
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentLayerAttributeInfo = $"查看操作异常: {ex.Message}";
ShowLayerAttributeInfo = true;
});
}
}
/// <summary>
/// 单独显示选中的分层
/// </summary>
private async Task IsolateSelectedLayerAsync()
{
try
{
LogManager.Info("[LayerManagementViewModel] 开始执行单独显示分层");
if (SelectedPreviewResult == null)
{
LogManager.Warning("[LayerManagementViewModel] 未选择任何预览结果");
return;
}
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
CurrentOperationText = "正在准备单独显示...";
UpdateMainStatus($"隐藏除'{SelectedPreviewResult.LayerName}'之外的其他分层");
});
// 2. 在UI线程执行Navisworks API调用
bool isolateResult = false;
string resultMessage = "";
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
try
{
// 获取选中分层的模型项
if (SelectedPreviewResult.Items == null || SelectedPreviewResult.Items.Count == 0)
{
LogManager.Warning($"[LayerManagementViewModel] 选中分层 '{SelectedPreviewResult.LayerName}' 没有模型项");
isolateResult = false;
resultMessage = "选中的分层没有模型项";
return;
}
// 调用可见性管理器的公共工具函数
bool success = VisibilityHelper.IsolateSpecificItems(SelectedPreviewResult.Items);
LogManager.Info($"[LayerManagementViewModel] 单独显示执行结果: {success}");
isolateResult = success;
resultMessage = success ? "已隔离显示项目" : "隔离显示失败";
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 单独显示执行异常: {ex.Message}", ex);
isolateResult = false;
resultMessage = $"执行异常: {ex.Message}";
}
});
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (isolateResult)
{
CurrentOperationText = $"已单独显示: {SelectedPreviewResult.LayerName}";
UpdateMainStatus("其他分层已隐藏,您可以预览选中的分层内容");
}
else
{
CurrentOperationText = "单独显示失败";
UpdateMainStatus(resultMessage ?? "请检查日志了解详细信息");
}
});
LogManager.Info($"[LayerManagementViewModel] 单独显示分层完成: {isolateResult}");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 单独显示分层异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "单独显示异常";
UpdateMainStatus($"操作失败: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
/// <summary>
/// 显示所有分层(恢复可见性)
/// </summary>
private async Task ShowAllLayersAsync()
{
try
{
LogManager.Info("[LayerManagementViewModel] 开始恢复所有分层显示");
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
CurrentOperationText = "正在恢复显示...";
UpdateMainStatus("恢复所有分层的可见性");
});
// 2. 在UI线程执行Navisworks API调用
bool restoreResult = false;
string resultMessage = "";
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
try
{
// 调用可见性管理器的公共工具函数
bool success = VisibilityHelper.ShowAllItems();
LogManager.Info($"[LayerManagementViewModel] 恢复显示执行结果: {success}");
restoreResult = success;
resultMessage = success ? "所有项目已显示" : "显示失败";
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 恢复显示执行异常: {ex.Message}", ex);
restoreResult = false;
resultMessage = $"执行异常: {ex.Message}";
}
});
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (restoreResult)
{
CurrentOperationText = "已恢复所有分层显示";
UpdateMainStatus("所有分层内容都已可见");
}
else
{
CurrentOperationText = "恢复显示失败";
UpdateMainStatus(resultMessage ?? "请检查日志了解详细信息");
}
});
LogManager.Info($"[LayerManagementViewModel] 恢复所有分层显示完成: {restoreResult}");
}
catch (Exception ex)
{
LogManager.Error($"[LayerManagementViewModel] 恢复所有分层显示异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
CurrentOperationText = "恢复显示异常";
UpdateMainStatus($"操作失败: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
#endregion
}
}