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

1257 lines
45 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.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.Commands;
using NavisworksTransport.UI.WPF.Collections;
using NavisworksTransport.UI.WPF.Commands;
using NavisworksTransport.UI.WPF.Models;
using NavisworksTransport.Utils;
namespace NavisworksTransport.UI.WPF.ViewModels
{
/// <summary>
/// 类别设置页签的ViewModel - 基于分层管理页签的设计风格
///
/// 功能特点:
/// 1. 参考分层管理页签的布局风格和UI组织方式
/// 2. 将模型选择提示移动到类别属性区域中
/// 3. 提供完整的物流属性设置功能
/// 4. 支持批量属性设置和单个模型编辑
/// 5. 使用MVVM架构和线程安全的UI更新
/// </summary>
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 = true;
private int _priority = 5;
private double _widthLimit = 3.0;
private double _heightLimit = 3.0;
private double _speedLimit = 0.8;
private bool _isLogisticsOnlyMode = false;
private LogisticsModel _selectedLogisticsModel;
#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 SelectedModelsText
{
get => _selectedModelsText;
set => SetPropertyThreadSafe(ref _selectedModelsText, value);
}
/// <summary>
/// 可用类别集合 - 使用线程安全集合
/// </summary>
public ThreadSafeObservableCollection<string> AvailableCategories { get; } =
new ThreadSafeObservableCollection<string>();
/// <summary>
/// 选中的类别
/// </summary>
public string SelectedCategory
{
get => _selectedCategory;
set
{
if (SetPropertyThreadSafe(ref _selectedCategory, value))
{
OnPropertyChanged(nameof(CanSetLogisticsAttribute));
}
}
}
/// <summary>
/// 是否可通行
/// </summary>
public bool IsTraversable
{
get => _isTraversable;
set => SetPropertyThreadSafe(ref _isTraversable, value);
}
/// <summary>
/// 优先级列表 - 使用线程安全集合
/// </summary>
public ThreadSafeObservableCollection<int> PriorityLevels { get; } =
new ThreadSafeObservableCollection<int> { 1, 2, 3, 4, 5 };
/// <summary>
/// 优先级1-5级5为最高
/// </summary>
public int Priority
{
get => _priority;
set => SetPropertyThreadSafe(ref _priority, value);
}
/// <summary>
/// 宽度限制(米)
/// </summary>
public double WidthLimit
{
get => _widthLimit;
set => SetPropertyThreadSafe(ref _widthLimit, value);
}
/// <summary>
/// 高度限制(米)
/// </summary>
public double HeightLimit
{
get => _heightLimit;
set => SetPropertyThreadSafe(ref _heightLimit, value);
}
/// <summary>
/// 限速(米/秒)
/// </summary>
public double SpeedLimit
{
get => _speedLimit;
set => SetPropertyThreadSafe(ref _speedLimit, value);
}
/// <summary>
/// 是否可以设置物流属性
/// </summary>
public bool CanSetLogisticsAttribute =>
!string.IsNullOrEmpty(SelectedCategory) &&
!IsProcessing &&
HasSelectedModels;
/// <summary>
/// 是否可以清除物流属性
/// </summary>
public bool CanClearLogisticsAttribute =>
!IsProcessing &&
HasSelectedModels &&
HasSelectedModelsWithLogisticsAttributes;
/// <summary>
/// 是否有选中的模型
/// </summary>
public bool HasSelectedModels
{
get
{
try
{
var document = NavisApplication.ActiveDocument;
return document?.CurrentSelection?.SelectedItems?.Count > 0;
}
catch
{
return false;
}
}
}
/// <summary>
/// 选中的模型是否包含物流属性
/// </summary>
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;
}
}
}
/// <summary>
/// 物流模型集合 - 使用线程安全集合
/// </summary>
public ThreadSafeObservableCollection<LogisticsModel> LogisticsModels { get; } =
new ThreadSafeObservableCollection<LogisticsModel>();
/// <summary>
/// 选中的物流模型
/// </summary>
/// <summary>
/// 选中的物流模型
/// </summary>
public LogisticsModel SelectedLogisticsModel
{
get => _selectedLogisticsModel;
set
{
if (SetPropertyThreadSafe(ref _selectedLogisticsModel, value))
{
// 选中Navisworks中对应的模型
SelectModelInNavisworks(value);
// 回填属性值到UI
LoadModelAttributes(value);
}
}
}
/// <summary>
/// 加载模型属性并回填到UI
/// </summary>
/// <param name="logisticsModel">选中的物流模型</param>
/// <summary>
/// 加载模型属性并回填到UI
/// </summary>
/// <param name="logisticsModel">选中的物流模型</param>
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");
}
/// <summary>
/// 是否处于仅显示物流模式
/// </summary>
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状态管理器实例和设置主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
/// <summary>
/// 初始化命令使用Command Pattern框架
/// </summary>
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<LogisticsModel>(
async (model) => await ToggleModelVisibilityAsync(model),
(model) => model != null && IsNotProcessing);
LogManager.Info("类别设置命令初始化完成 - 使用统一Command Pattern框架");
}, "初始化命令");
}
#endregion
#region - 使UIStateManager
/// <summary>
/// 刷新选择状态 - 使用新的选择管理服务
/// </summary>
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;
});
}
}
/// <summary>
/// 设置物流属性 - 实现正确的业务逻辑与UI分离模式
/// </summary>
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<CategoryAttributeManager.LogisticsElementType>(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;
});
}
}
/// <summary>
/// 清除物流属性 - 实现正确的业务逻辑与UI分离模式
/// </summary>
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;
});
}
}
/// <summary>
/// 刷新物流模型列表 - 实现正确的业务逻辑与UI分离模式
/// </summary>
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<LogisticsModel>();
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<LogisticsModel>(), 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;
});
}
}
/// <summary>
/// 重置为默认值 - 实现正确的业务逻辑与UI分离模式
/// </summary>
private async Task ResetToDefaultsAsync()
{
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
SelectedCategory = "通道";
IsTraversable = true;
Priority = 5;
WidthLimit = 3.0;
HeightLimit = 3.0;
SpeedLimit = 0.8;
UpdateMainStatus("已重置为默认值");
LogManager.Info("已重置类别设置为默认值");
});
}
/// <summary>
/// 切换模型可见性
/// </summary>
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;
});
}
}
/// <summary>
/// 在Navisworks中选择对应的模型
/// </summary>
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
/// <summary>
/// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
/// </summary>
private void SubscribeToSelectionEvents()
{
try
{
// 使用新的选择管理服务订阅选择变化事件
_selectionEventSubscription = NavisworksSelectionHelper.SubscribeToSelectionChanges(
OnSelectionChangedAsync, _uiStateManager);
LogManager.Info("[ModelSettingsViewModel] 已通过NavisworksSelectionHelper订阅选择变化事件");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 订阅选择事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅Navisworks选择变化事件 - 使用新的选择管理服务
/// </summary>
private void UnsubscribeFromSelectionEvents()
{
try
{
// 通过Dispose方法取消订阅
_selectionEventSubscription?.Dispose();
_selectionEventSubscription = null;
LogManager.Info("[ModelSettingsViewModel] 已通过NavisworksSelectionHelper取消订阅选择变化事件");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 取消选择事件订阅失败: {ex.Message}", ex);
}
}
/// <summary>
/// 选择变化事件处理器 - 使用新的选择管理服务
/// </summary>
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);
}
}
/// <summary>
/// 更新模型选择状态 - 使用新的选择管理服务
/// </summary>
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
/// <summary>
/// 异步初始化
/// </summary>
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("初始化失败,请检查日志");
});
}
}
/// <summary>
/// 应用可见性模式
/// </summary>
private void ApplyVisibilityMode()
{
SafeExecute(() =>
{
if (IsLogisticsOnlyMode)
{
ShowLogisticsOnlyInternal();
}
else
{
ShowAllInternal();
}
}, "应用可见性模式");
}
/// <summary>
/// 内部方法:显示所有元素
/// </summary>
private void ShowAllInternal()
{
bool success = VisibilityHelper.ShowAllItems();
if (success)
{
foreach (var model in LogisticsModels)
{
model.IsVisible = true;
}
UpdateMainStatus("显示所有元素");
LogManager.Info("切换到显示全部模式");
}
else
{
UpdateMainStatus("显示全部失败");
LogManager.Error("显示全部失败");
}
}
/// <summary>
/// 内部方法:仅显示物流元素
/// </summary>
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}");
}
}
/// <summary>
/// 格式化物流属性为显示字符串
/// </summary>
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
/// <summary>
/// 向后兼容提供UIStateManager访问接口
/// </summary>
public UIStateManager UIStateManager => _uiStateManager;
/// <summary>
/// 验证ViewModel状态是否正常
/// </summary>
public bool IsValidState()
{
return _uiStateManager != null &&
AvailableCategories != null &&
LogisticsModels != null &&
PriorityLevels != null;
}
/// <summary>
/// 获取ViewModel状态信息
/// </summary>
public string GetStateInfo()
{
return $"UIStateManager: {(_uiStateManager != null ? "" : "")}, " +
$"可用类别数量: {AvailableCategories?.Count ?? 0}, " +
$"物流模型数量: {LogisticsModels?.Count ?? 0}";
}
/// <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
{
// 取消选择事件订阅
UnsubscribeFromSelectionEvents();
LogManager.Info("[ModelSettingsViewModel] 资源清理完成");
}
catch (Exception ex)
{
LogManager.Error($"[ModelSettingsViewModel] 资源清理失败: {ex.Message}");
}
}
_disposed = true;
}
}
#endregion
}
}