using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Autodesk.Navisworks.Api;
using NavisApplication = Autodesk.Navisworks.Api.Application;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Commands;
using NavisworksTransport.UI.WPF.Collections;
using NavisworksTransport.UI.WPF.Commands;
using NavisworksTransport.UI.WPF.Models;
using NavisworksTransport.Utils;
namespace NavisworksTransport.UI.WPF.ViewModels
{
///
/// 类别设置页签的ViewModel - 基于分层管理页签的设计风格
///
/// 功能特点:
/// 1. 参考分层管理页签的布局风格和UI组织方式
/// 2. 将模型选择提示移动到类别属性区域中
/// 3. 提供完整的物流属性设置功能
/// 4. 支持批量属性设置和单个模型编辑
/// 5. 使用MVVM架构和线程安全的UI更新
///
public class ModelSettingsViewModel : ViewModelBase, IDisposable
{
#region 私有字段和依赖注入
private readonly UIStateManager _uiStateManager;
// 选择事件订阅管理器
private SelectionEventSubscription _selectionEventSubscription;
// 资源释放状态标志
private bool _disposed;
#endregion
#region 状态字段
private bool _isProcessing;
private string _selectedModelsText;
private string _selectedCategory;
private bool _isTraversable;
private int _priority;
private double _widthLimit;
private double _heightLimit;
private double _speedLimit;
private bool _isLogisticsOnlyMode;
private LogisticsModel _selectedLogisticsModel;
#endregion
#region 公共属性 - 使用线程安全的SetProperty方法
///
/// 是否正在处理中
///
public bool IsProcessing
{
get => _isProcessing;
set
{
if (SetPropertyThreadSafe(ref _isProcessing, value))
{
OnPropertyChanged(nameof(IsNotProcessing));
RefreshAllCommands();
}
}
}
///
/// 是否未在处理中
///
public bool IsNotProcessing => !IsProcessing;
///
/// 选中模型文本
///
public string SelectedModelsText
{
get => _selectedModelsText;
set => SetPropertyThreadSafe(ref _selectedModelsText, value);
}
///
/// 可用类别集合 - 使用线程安全集合
///
public ThreadSafeObservableCollection AvailableCategories { get; } =
new ThreadSafeObservableCollection();
///
/// 选中的类别
///
public string SelectedCategory
{
get => _selectedCategory;
set
{
if (SetPropertyThreadSafe(ref _selectedCategory, value))
{
OnPropertyChanged(nameof(CanSetLogisticsAttribute));
}
}
}
///
/// 是否可通行
///
public bool IsTraversable
{
get => _isTraversable;
set => SetPropertyThreadSafe(ref _isTraversable, value);
}
///
/// 优先级列表 - 使用线程安全集合
///
public ThreadSafeObservableCollection PriorityLevels { get; } =
new ThreadSafeObservableCollection { 1, 2, 3, 4, 5 };
///
/// 优先级(1-5级,5为最高)
///
public int Priority
{
get => _priority;
set => SetPropertyThreadSafe(ref _priority, value);
}
///
/// 宽度限制(米)
///
public double WidthLimit
{
get => _widthLimit;
set => SetPropertyThreadSafe(ref _widthLimit, value);
}
///
/// 高度限制(米)
///
public double HeightLimit
{
get => _heightLimit;
set => SetPropertyThreadSafe(ref _heightLimit, value);
}
///
/// 限速(米/秒)
///
public double SpeedLimit
{
get => _speedLimit;
set => SetPropertyThreadSafe(ref _speedLimit, value);
}
///
/// 是否可以设置物流属性
///
public bool CanSetLogisticsAttribute =>
!string.IsNullOrEmpty(SelectedCategory) &&
!IsProcessing &&
HasSelectedModels;
///
/// 是否可以清除物流属性
///
public bool CanClearLogisticsAttribute =>
!IsProcessing &&
HasSelectedModels &&
HasSelectedModelsWithLogisticsAttributes;
///
/// 是否有选中的模型
///
public bool HasSelectedModels
{
get
{
try
{
var document = NavisApplication.ActiveDocument;
return document?.CurrentSelection?.SelectedItems?.Count > 0;
}
catch
{
return false;
}
}
}
///
/// 选中的模型是否包含物流属性
///
public bool HasSelectedModelsWithLogisticsAttributes
{
get
{
try
{
var document = NavisApplication.ActiveDocument;
var selectedItems = document?.CurrentSelection?.SelectedItems;
if (selectedItems == null || selectedItems.Count == 0)
return false;
// 检查是否至少有一个选中的模型具有物流属性
foreach (var item in selectedItems)
{
if (CategoryAttributeManager.HasLogisticsAttributes(item))
{
return true;
}
}
return false;
}
catch
{
return false;
}
}
}
///
/// 物流模型集合 - 使用线程安全集合
///
public ThreadSafeObservableCollection LogisticsModels { get; } =
new ThreadSafeObservableCollection();
///
/// 选中的物流模型
///
///
/// 选中的物流模型
///
public LogisticsModel SelectedLogisticsModel
{
get => _selectedLogisticsModel;
set
{
if (SetPropertyThreadSafe(ref _selectedLogisticsModel, value))
{
// 选中Navisworks中对应的模型
SelectModelInNavisworks(value);
// 回填属性值到UI
LoadModelAttributes(value);
}
}
}
///
/// 加载模型属性并回填到UI
///
/// 选中的物流模型
///
/// 加载模型属性并回填到UI
///
/// 选中的物流模型
private void LoadModelAttributes(LogisticsModel logisticsModel)
{
if (logisticsModel?.NavisworksItem == null)
{
LogManager.Error($"[ModelSettingsViewModel] 异常:试图加载空的物流模型或NavisworksItem!");
return;
}
// 从Navisworks项中获取物流属性信息
var info = CategoryAttributeManager.GetLogisticsAttributeInfo(logisticsModel.NavisworksItem);
if (info == null)
{
LogManager.Error($"[ModelSettingsViewModel] 异常:列表中的模型 {logisticsModel.Name} 没有物流属性信息!");
return;
}
// 验证物流类型
if (string.IsNullOrEmpty(info.ElementType))
{
LogManager.Error($"[ModelSettingsViewModel] 异常:模型 {logisticsModel.Name} 的ElementType为空!");
return;
}
if (!AvailableCategories.Contains(info.ElementType))
{
LogManager.Error($"[ModelSettingsViewModel] 异常:模型 {logisticsModel.Name} 的ElementType '{info.ElementType}' 不在可用类别中!");
return;
}
// 验证优先级
if (info.Priority < 1 || info.Priority > 5)
{
LogManager.Error($"[ModelSettingsViewModel] 异常:模型 {logisticsModel.Name} 的优先级 {info.Priority} 超出有效范围(1-5)!");
return;
}
// 验证高度限制
if (info.HeightLimit <= 0)
{
LogManager.Error($"[ModelSettingsViewModel] 异常:模型 {logisticsModel.Name} 的高度限制 {info.HeightLimit} 无效!");
return;
}
// 验证速度限制
if (info.SpeedLimit <= 0)
{
LogManager.Error($"[ModelSettingsViewModel] 异常:模型 {logisticsModel.Name} 的速度限制 {info.SpeedLimit} 无效!");
return;
}
// 验证宽度限制
if (info.WidthLimit <= 0)
{
LogManager.Error($"[ModelSettingsViewModel] 异常:模型 {logisticsModel.Name} 的宽度限制 {info.WidthLimit} 无效!");
return;
}
// 所有验证通过,回填属性
SelectedCategory = info.ElementType;
IsTraversable = info.IsTraversable;
Priority = info.Priority;
HeightLimit = info.HeightLimit;
SpeedLimit = info.SpeedLimit;
WidthLimit = info.WidthLimit;
LogManager.Info($"[ModelSettingsViewModel] 已回填模型属性: {logisticsModel.Name}, 类型: {info.ElementType}, 可通行: {info.IsTraversable}, 优先级: {info.Priority}, 高度: {info.HeightLimit}m, 速度: {info.SpeedLimit}m/s, 宽度: {info.WidthLimit}m");
}
///
/// 是否处于仅显示物流模式
///
public bool IsLogisticsOnlyMode
{
get => _isLogisticsOnlyMode;
set
{
if (SetPropertyThreadSafe(ref _isLogisticsOnlyMode, value))
{
// 当开关状态改变时,自动应用可见性设置
ApplyVisibilityMode();
}
}
}
#endregion
#region 命令 - 使用统一的Command Pattern
public ICommand RefreshSelectionCommand { get; private set; }
public ICommand SetLogisticsAttributeCommand { get; private set; }
public ICommand ClearLogisticsAttributeCommand { get; private set; }
public ICommand RefreshLogisticsModelsCommand { get; private set; }
public ICommand ResetToDefaultsCommand { get; private set; }
public ICommand ToggleModelVisibilityCommand { get; private set; }
#endregion
#region 构造函数 - 使用依赖注入和统一架构
public ModelSettingsViewModel(LogisticsControlViewModel mainViewModel = null) : base()
{
try
{
// 从配置文件初始化默认值(必须在UI绑定之前完成)
var config = ConfigManager.Instance.Current;
_selectedModelsText = "请在主界面中选择需要设置的模型";
_selectedCategory = "通道";
_isTraversable = config.Logistics.Traversable;
_priority = config.Logistics.Priority;
_widthLimit = config.Logistics.WidthLimitMeters;
_heightLimit = config.Logistics.HeightLimitMeters;
_speedLimit = config.Logistics.SpeedLimitMetersPerSecond;
_isLogisticsOnlyMode = false;
// 获取UI状态管理器实例和设置主ViewModel引用到基类
_uiStateManager = UIStateManager.Instance;
SetMainViewModel(mainViewModel);
// 验证关键组件是否正常初始化
if (_uiStateManager == null)
{
LogManager.Error("UIStateManager初始化失败");
throw new InvalidOperationException("UIStateManager初始化失败");
}
// 初始化命令
InitializeCommands();
// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
SubscribeToSelectionEvents();
// 异步初始化
InitializeAsync();
LogManager.Info("ModelSettingsViewModel构造函数执行完成 - 使用统一UI架构");
}
catch (Exception ex)
{
LogManager.Error($"ModelSettingsViewModel构造函数异常: {ex.Message}", ex);
UpdateMainStatus("初始化失败,请检查日志");
throw;
}
}
#endregion
#region 命令初始化 - 统一的Command Pattern
///
/// 初始化命令(使用Command Pattern框架)
///
private void InitializeCommands()
{
SafeExecute(() =>
{
RefreshSelectionCommand = new RelayCommand(
async () => await RefreshSelectionAsync(),
() => IsNotProcessing);
SetLogisticsAttributeCommand = new RelayCommand(
async () => await SetLogisticsAttributeAsync(),
() => CanSetLogisticsAttribute);
ClearLogisticsAttributeCommand = new RelayCommand(
async () => await ClearLogisticsAttributeAsync(),
() => CanClearLogisticsAttribute);
RefreshLogisticsModelsCommand = new RelayCommand(
async () => await RefreshLogisticsModelsAsync(),
() => IsNotProcessing);
ResetToDefaultsCommand = new RelayCommand(
async () => await ResetToDefaultsAsync(),
() => IsNotProcessing);
ToggleModelVisibilityCommand = new RelayCommand(
async (model) => await ToggleModelVisibilityAsync(model),
(model) => model != null && IsNotProcessing);
LogManager.Info("类别设置命令初始化完成 - 使用统一Command Pattern框架");
}, "初始化命令");
}
#endregion
#region 业务逻辑方法 - 使用统一的UIStateManager
///
/// 刷新选择状态 - 使用新的选择管理服务
///
private async Task RefreshSelectionAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
UpdateMainStatus("正在检查模型选择...", -1, true);
});
try
{
// 2. 使用新的选择管理服务获取选择状态(后台线程)
var selectionResult = await NavisworksSelectionHelper.GetCurrentSelectionStateAsync();
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (selectionResult.Success)
{
SelectedModelsText = NavisworksSelectionHelper.FormatSelectionText(selectionResult, "个模型");
UpdateMainStatus("检查完成");
}
else
{
SelectedModelsText = selectionResult.ErrorMessage ?? "检查选择状态失败";
UpdateMainStatus("检查失败");
}
// 🔧 修复:刷新所有与选择相关的命令状态(包括清除属性按钮)
OnPropertyChanged(nameof(HasSelectedModels));
OnPropertyChanged(nameof(HasSelectedModelsWithLogisticsAttributes));
OnPropertyChanged(nameof(CanSetLogisticsAttribute));
OnPropertyChanged(nameof(CanClearLogisticsAttribute));
});
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 刷新选择异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedModelsText = "检查选择状态异常";
UpdateMainStatus($"检查失败: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
///
/// 设置物流属性 - 实现正确的业务逻辑与UI分离模式
///
private async Task SetLogisticsAttributeAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
UpdateMainStatus("正在设置物流属性...", -1, true);
});
try
{
// 2. 纯业务逻辑执行(后台线程,不使用UIStateManager)
var result = await Task.Run(() =>
{
try
{
var selectedItems = NavisApplication.ActiveDocument?.CurrentSelection?.SelectedItems;
if (selectedItems == null || selectedItems.Count == 0)
{
return new { Success = false, Count = 0, Message = "请先选择模型元素" };
}
// 解析选中的类别为枚举
if (Enum.TryParse(SelectedCategory, out var elementType))
{
int successCount = CategoryAttributeManager.AddLogisticsAttributes(
selectedItems,
elementType,
isTraversable: IsTraversable,
priority: Priority,
heightLimit: HeightLimit,
speedLimit: SpeedLimit,
widthLimit: WidthLimit);
return new {
Success = true,
Count = successCount,
Message = $"已为 {successCount} 个元素设置物流属性: {SelectedCategory}"
};
}
else
{
return new { Success = false, Count = 0, Message = $"无效的物流类别: {SelectedCategory}" };
}
}
catch (Exception ex)
{
return new { Success = false, Count = 0, Message = $"设置属性失败: {ex.Message}" };
}
});
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus(result.Message);
if (result.Success)
{
LogManager.Info($"设置物流属性成功: {result.Message}");
}
else
{
LogManager.Warning($"设置物流属性失败: {result.Message}");
}
});
// 如果设置成功,异步刷新物流模型列表
if (result.Success)
{
await RefreshLogisticsModelsAsync();
// 如果当前处于仅显示物流模式,重新应用可见性设置
if (IsLogisticsOnlyMode)
{
// 重要:ApplyVisibilityMode包含Navisworks API调用,必须在主线程中执行
ApplyVisibilityMode();
}
}
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 设置物流属性异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus($"设置属性出错: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
///
/// 清除物流属性 - 实现正确的业务逻辑与UI分离模式
///
private async Task ClearLogisticsAttributeAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
UpdateMainStatus("正在清除物流属性...", -1, true);
});
try
{
// 2. 纯业务逻辑执行(后台线程,不使用UIStateManager)
var result = await Task.Run(() =>
{
try
{
var selectedItems = NavisApplication.ActiveDocument?.CurrentSelection?.SelectedItems;
if (selectedItems == null || selectedItems.Count == 0)
{
return new { Success = false, Count = 0, Message = "请先选择模型元素" };
}
// 使用CategoryAttributeManager的RemoveLogisticsAttributes方法
int successCount = CategoryAttributeManager.RemoveLogisticsAttributes(selectedItems);
return new {
Success = successCount > 0,
Count = successCount,
Message = successCount > 0 ?
$"已清除 {successCount} 个元素的物流属性" :
"没有找到可清除的物流属性"
};
}
catch (Exception ex)
{
return new { Success = false, Count = 0, Message = $"清除属性失败: {ex.Message}" };
}
});
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus(result.Message);
if (result.Success)
{
LogManager.Info($"清除物流属性成功: {result.Message}");
}
else
{
LogManager.Warning($"清除物流属性失败: {result.Message}");
}
});
// 如果清除成功,异步刷新物流模型列表
if (result.Success)
{
await RefreshLogisticsModelsAsync();
// 如果当前处于仅显示物流模式,重新应用可见性设置
if (IsLogisticsOnlyMode)
{
// 重要:ApplyVisibilityMode包含Navisworks API调用,必须在主线程中执行
ApplyVisibilityMode();
}
}
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 清除物流属性异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus($"清除属性出错: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
///
/// 刷新物流模型列表 - 实现正确的业务逻辑与UI分离模式
///
private async Task RefreshLogisticsModelsAsync()
{
// 1. 初始UI状态更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
UpdateMainStatus("正在刷新物流模型列表...", -1, true);
});
try
{
// 2. 纯业务逻辑执行(后台线程,不使用UIStateManager)
var result = await Task.Run(() =>
{
try
{
// 直接使用 CategoryAttributeManager 的 API
var document = NavisApplication.ActiveDocument;
var logisticsItems = CategoryAttributeManager.GetAllLogisticsItems();
var models = new List();
foreach (var item in logisticsItems)
{
// 直接使用 CategoryAttributeManager 的 API
var info = CategoryAttributeManager.GetLogisticsAttributeInfo(item);
var model = new LogisticsModel
{
Name = item.DisplayName ?? "未命名模型",
Category = info?.ElementType ?? "未分类",
Attributes = FormatLogisticsAttributes(info),
IsVisible = !item.IsHidden,
NavisworksItem = item
};
models.Add(model);
}
return new { Success = true, Models = models, Count = models.Count };
}
catch (Exception ex)
{
LogManager.Error($"刷新物流模型列表异常: {ex.Message}", ex);
return new { Success = false, Models = new List(), Count = 0 };
}
});
// 3. 结果UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
LogisticsModels.Clear();
if (result.Success)
{
foreach (var model in result.Models)
{
LogisticsModels.Add(model);
}
UpdateMainStatus($"已刷新物流模型列表,共 {result.Count} 个模型");
}
else
{
UpdateMainStatus("刷新物流模型列表失败");
}
});
LogManager.Info($"已刷新所有物流模型列表,共 {result.Count} 个模型");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 刷新物流模型异常: {ex.Message}", ex);
// 异常UI更新
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
LogisticsModels.Clear();
UpdateMainStatus($"刷新列表出错: {ex.Message}");
});
}
finally
{
// 4. 清理UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
///
/// 重置为默认值 - 从配置文件读取默认值
///
private async Task ResetToDefaultsAsync()
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
var config = ConfigManager.Instance.Current;
SelectedCategory = "通道";
IsTraversable = config.Logistics.Traversable;
Priority = config.Logistics.Priority;
WidthLimit = config.Logistics.WidthLimitMeters;
HeightLimit = config.Logistics.HeightLimitMeters;
SpeedLimit = config.Logistics.SpeedLimitMetersPerSecond;
UpdateMainStatus("已重置为默认值(来自配置)");
LogManager.Info($"已重置类别设置为默认值 - 可通行:{IsTraversable}, 优先级:{Priority}, 宽度:{WidthLimit:F1}m, 高度:{HeightLimit:F1}m, 速度:{SpeedLimit:F1}m/s");
});
}
///
/// 切换模型可见性
///
private async Task ToggleModelVisibilityAsync(LogisticsModel model)
{
if (model?.NavisworksItem == null) return;
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = true;
});
try
{
// 重要:Navisworks API 操作必须在主线程中执行,不能在Task.Run中
var newVisibility = !model.IsVisible;
// 使用VisibilityHelper来切换单个模型的可见性
var itemCollection = new ModelItemCollection { model.NavisworksItem };
bool success = VisibilityHelper.SetItemsVisibility(itemCollection, !newVisibility);
// 更新UI状态
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
if (success)
{
model.IsVisible = newVisibility;
var action = newVisibility ? "显示" : "隐藏";
UpdateMainStatus($"已{action}模型: {model.Name}");
LogManager.Info($"成功{action}模型: {model.Name}");
}
else
{
UpdateMainStatus($"切换模型可见性失败: {model.Name}");
LogManager.Error($"切换模型可见性失败: {model.Name}");
}
});
}
catch (Exception ex)
{
LogManager.Error($"ToggleModelVisibilityAsync异常: {ex.Message}", ex);
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus($"切换可见性异常: {ex.Message}");
});
}
finally
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
IsProcessing = false;
});
}
}
///
/// 在Navisworks中选择对应的模型
///
private void SelectModelInNavisworks(LogisticsModel model)
{
// 重要:根据示例代码,选择操作必须在主线程中执行,不能在Task.Run中
try
{
if (model?.NavisworksItem == null)
{
// 如果没有选中模型,清除Navisworks选择
bool success = NavisworksSelectionHelper.SetModelSelection((ModelItem)null);
if (success)
{
LogManager.Info("已清除Navisworks选择");
}
else
{
LogManager.Warning("清除Navisworks选择失败");
}
}
else
{
// 选择指定的模型项
bool success = NavisworksSelectionHelper.SetModelSelection(model.NavisworksItem);
if (success)
{
LogManager.Info($"已在Navisworks中选择模型: {model.Name}");
}
else
{
LogManager.Warning($"在Navisworks中选择模型失败: {model.Name}");
}
}
}
catch (Exception ex)
{
LogManager.Error($"在Navisworks中选择模型失败: {ex.Message}", ex);
}
}
#endregion
// 选择状态格式化方法已移至NavisworksSelectionHelper中
#region 选择事件处理
///
/// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
///
private void SubscribeToSelectionEvents()
{
try
{
// 使用新的选择管理服务订阅选择变化事件
_selectionEventSubscription = NavisworksSelectionHelper.SubscribeToSelectionChanges(
OnSelectionChangedAsync, _uiStateManager);
LogManager.Info("[ModelSettingsViewModel] 已通过NavisworksSelectionHelper订阅选择变化事件");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 订阅选择事件失败: {ex.Message}", ex);
}
}
///
/// 取消订阅Navisworks选择变化事件 - 使用新的选择管理服务
///
private void UnsubscribeFromSelectionEvents()
{
try
{
// 通过Dispose方法取消订阅
_selectionEventSubscription?.Dispose();
_selectionEventSubscription = null;
LogManager.Info("[ModelSettingsViewModel] 已通过NavisworksSelectionHelper取消订阅选择变化事件");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 取消选择事件订阅失败: {ex.Message}", ex);
}
}
///
/// 选择变化事件处理器 - 使用新的选择管理服务
///
private async Task OnSelectionChangedAsync(SelectionStateResult selectionResult)
{
// 如果已经释放,直接返回
if (_disposed) return;
try
{
// 更新物流属性相关的选择状态(使用新的选择结果)
await UpdateModelSelectionStateAsync(selectionResult);
LogManager.Info($"[ModelSettingsViewModel] 选择状态已更新: {selectionResult.Count}个项目");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 处理选择变化事件异常: {ex.Message}", ex);
}
}
///
/// 更新模型选择状态 - 使用新的选择管理服务
///
private async Task UpdateModelSelectionStateAsync(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(HasSelectedModels));
OnPropertyChanged(nameof(HasSelectedModelsWithLogisticsAttributes));
OnPropertyChanged(nameof(CanSetLogisticsAttribute));
OnPropertyChanged(nameof(CanClearLogisticsAttribute));
LogManager.Info($"[ModelSettingsViewModel] 模型选择状态已更新: 成功={selectionResult.Success}, 数量={selectionResult.Count}");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 更新模型选择状态异常: {ex.Message}", ex);
SelectedModelsText = "检查选择状态异常";
}
}
#endregion
#region 辅助方法
///
/// 异步初始化
///
private async void InitializeAsync()
{
try
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
// 初始化物流类别
AvailableCategories.Clear();
foreach (var elementType in Enum.GetValues(typeof(CategoryAttributeManager.LogisticsElementType)))
{
AvailableCategories.Add(elementType.ToString());
}
// 设置默认选择
if (AvailableCategories.Count > 0 && AvailableCategories.Contains("通道"))
{
SelectedCategory = "通道";
}
else if (AvailableCategories.Count > 0)
{
SelectedCategory = AvailableCategories[0];
}
});
// 刷新选择状态
await RefreshSelectionAsync();
// 刷新物流模型列表
await RefreshLogisticsModelsAsync();
// 🔧 确保初始化完成后所有Command状态正确
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
RefreshAllCommands();
UpdateMainStatus("分层属性设置已就绪");
});
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 初始化失败: {ex.Message}");
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
UpdateMainStatus("初始化失败,请检查日志");
});
}
}
///
/// 应用可见性模式
///
private void ApplyVisibilityMode()
{
SafeExecute(() =>
{
if (IsLogisticsOnlyMode)
{
ShowLogisticsOnlyInternal();
}
else
{
ShowAllInternal();
}
}, "应用可见性模式");
}
///
/// 内部方法:显示所有元素
///
private void ShowAllInternal()
{
bool success = VisibilityHelper.ShowAllItems();
if (success)
{
foreach (var model in LogisticsModels)
{
model.IsVisible = true;
}
UpdateMainStatus("显示所有元素");
LogManager.Info("切换到显示全部模式");
}
else
{
UpdateMainStatus("显示全部失败");
LogManager.Error("显示全部失败");
}
}
///
/// 内部方法:仅显示物流元素
///
private void ShowLogisticsOnlyInternal()
{
try
{
LogManager.Info("[UI-ModelSettings] 开始仅显示物流元素");
var document = NavisApplication.ActiveDocument;
if (document == null || document.Models == null)
{
LogManager.Warning("[UI-ModelSettings] 没有活动文档");
UpdateMainStatus("没有活动文档");
return;
}
var logisticsItems = CategoryAttributeManager.GetAllLogisticsItems();
if (logisticsItems == null || logisticsItems.Count == 0)
{
LogManager.Info("[UI-ModelSettings] 没有找到物流元素");
UpdateMainStatus("未找到物流元素");
return;
}
LogManager.Info($"[UI-ModelSettings] 找到 {logisticsItems.Count} 个物流元素");
bool success = VisibilityHelper.IsolateSpecificItems(logisticsItems);
if (success)
{
// 更新物流模型列表中的可见性状态
foreach (var model in LogisticsModels)
{
model.IsVisible = true;
}
LogManager.Info($"[UI-ModelSettings] 成功隔离显示物流元素");
UpdateMainStatus($"仅显示物流元素 ({logisticsItems.Count} 个物流节点)");
}
else
{
LogManager.Error("[UI-ModelSettings] 隔离显示失败");
UpdateMainStatus("操作失败");
}
}
catch (Exception ex)
{
LogManager.Error($"[UI-ModelSettings] 仅显示物流元素失败:{ex.Message}");
UpdateMainStatus($"操作失败:{ex.Message}");
}
}
///
/// 格式化物流属性为显示字符串
///
private string FormatLogisticsAttributes(LogisticsAttributeInfo info)
{
if (info == null) return "无属性";
// 简单格式化:可通行、优先级、限制等
return $"可通行: {(info.IsTraversable ? "是" : "否")}, " +
$"优先级: {info.Priority}, " +
$"高度限制: {info.HeightLimit}m, " +
$"速度限制: {info.SpeedLimit}m/s";
}
private void RefreshAllCommands()
{
OnPropertyChanged(nameof(CanSetLogisticsAttribute));
OnPropertyChanged(nameof(CanClearLogisticsAttribute));
OnPropertyChanged(nameof(HasSelectedModels));
OnPropertyChanged(nameof(HasSelectedModelsWithLogisticsAttributes));
// 🔧 强制WPF重新查询所有Command的CanExecute状态
System.Windows.Input.CommandManager.InvalidateRequerySuggested();
}
#endregion
#region 向后兼容性接口
///
/// 向后兼容:提供UIStateManager访问接口
///
public UIStateManager UIStateManager => _uiStateManager;
///
/// 验证ViewModel状态是否正常
///
public bool IsValidState()
{
return _uiStateManager != null &&
AvailableCategories != null &&
LogisticsModels != null &&
PriorityLevels != null;
}
///
/// 获取ViewModel状态信息
///
public string GetStateInfo()
{
return $"UIStateManager: {(_uiStateManager != null ? "已初始化" : "未初始化")}, " +
$"可用类别数量: {AvailableCategories?.Count ?? 0}, " +
$"物流模型数量: {LogisticsModels?.Count ?? 0}";
}
///
/// 释放资源
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// 释放资源的具体实现
///
/// 是否正在释放托管资源
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
try
{
// 取消选择事件订阅
UnsubscribeFromSelectionEvents();
LogManager.Info("[ModelSettingsViewModel] 资源清理完成");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 资源清理失败: {ex.Message}");
}
}
_disposed = true;
}
}
#endregion
}
}