增加配置变更事件订阅,实现系统配置实时生效

This commit is contained in:
tian 2026-02-01 19:00:31 +08:00
parent b1461436ff
commit 1d3f46dd00
7 changed files with 725 additions and 4 deletions

View File

@ -6,7 +6,8 @@
1. [ ] 优化将ViewPonit的RenderStyle改成Shaded以免影响高亮考虑在显示碰撞时改成Wireframe
2、[ ] 优化修改架构适应模型坐标系的变化Yup-Xright-Zfront
3、[ ] (优化)修改吊装路径适应桁车空中路线(纵向+平移,有吊绳)
3、[x] (优化)修改吊装路径适应桁车空中路线(纵向+平移,有吊绳)
4、[x] (优化)对系统配置文件的修改即时起效
### [2026/1/26]

View File

@ -212,8 +212,104 @@ namespace NavisworksTransport.Core.Animation
// 订阅文档状态事件
DocumentStateManager.Instance.DocumentInvalidated += OnDocumentInvalidated;
// 订阅配置变更事件
SubscribeToConfigChanges();
}
#region
/// <summary>
/// 订阅配置变更事件
/// </summary>
private void SubscribeToConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged;
LogManager.Info("PathAnimationManager 已订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅配置变更事件
/// </summary>
private void UnsubscribeFromConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged;
LogManager.Info("PathAnimationManager 已取消订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}");
}
}
/// <summary>
/// 配置变更事件处理
/// </summary>
private void OnCategoryConfigurationChanged(object sender, Tuple<ConfigCategory, ConfigurationChangedEventArgs> args)
{
try
{
var category = args.Item1;
var eventArgs = args.Item2;
// 处理 Animation 类别变更
if (category == ConfigCategory.Animation || category == ConfigCategory.All)
{
LogManager.Info("收到 Animation 配置变更通知,正在更新动画参数...");
var config = ConfigManager.Instance.Current;
bool needReset = false;
// 检查帧率是否变更
if (_animationFrameRate != config.Animation.FrameRate)
{
_animationFrameRate = config.Animation.FrameRate;
_frameInterval = 1000.0 / _animationFrameRate;
// 更新定时器间隔
if (_animationTimer != null)
{
_animationTimer.Interval = TimeSpan.FromMilliseconds(_frameInterval);
}
needReset = true;
LogManager.Info($"动画帧率已更新: {_animationFrameRate} fps, 帧间隔: {_frameInterval:F1} ms");
}
// 检查持续时间是否变更
if (_animationDuration != config.Animation.DurationSeconds)
{
_animationDuration = config.Animation.DurationSeconds;
needReset = true;
LogManager.Info($"动画持续时间已更新: {_animationDuration} 秒");
}
// 如果动画正在运行,需要重置
if (needReset && (_currentState == AnimationState.Playing || _currentState == AnimationState.Paused))
{
// 停止当前动画,让用户重新生成
ShutdownAnimation();
LogManager.Info("动画参数已变更,当前动画已停止,请重新生成动画");
}
}
}
catch (Exception ex)
{
LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex);
}
}
#endregion
/// <summary>
/// 获取单例实例
/// </summary>
@ -2370,6 +2466,9 @@ namespace NavisworksTransport.Core.Animation
{
LogManager.Info("开始清理PathAnimationManager资源");
// 0. 取消配置变更事件订阅
UnsubscribeFromConfigChanges();
// 1. 优先停止动画(最小化的操作,不触发复杂的重置逻辑)
// 只有在动画运行时才停止,避免重复调用
try

View File

@ -7,11 +7,56 @@ using Tomlyn.Syntax;
namespace NavisworksTransport.Core.Config
{
/// <summary>
/// 配置变更类别
/// </summary>
public enum ConfigCategory
{
None = 0,
PathEditing = 1,
Visualization = 2,
Animation = 3,
Logistics = 4,
CoordinateSystem = 5,
GridGeneration = 6,
PathPlanning = 7,
All = 99
}
/// <summary>
/// 配置变更事件参数
/// </summary>
public class ConfigurationChangedEventArgs : EventArgs
{
/// <summary>
/// 变更的配置类别
/// </summary>
public ConfigCategory ChangedCategory { get; set; }
/// <summary>
/// 是否是外部文件修改触发的变更
/// </summary>
public bool IsExternalChange { get; set; }
/// <summary>
/// 变更时间戳
/// </summary>
public DateTime ChangeTime { get; set; }
public ConfigurationChangedEventArgs(ConfigCategory category, bool isExternal = false)
{
ChangedCategory = category;
IsExternalChange = isExternal;
ChangeTime = DateTime.Now;
}
}
/// <summary>
/// 系统配置管理器
/// 负责 TOML 配置文件的读取、保存和管理
/// 支持配置变更通知机制
/// </summary>
public class ConfigManager
public class ConfigManager : IDisposable
{
private static ConfigManager _instance;
private static readonly object _lock = new object();
@ -37,6 +82,18 @@ namespace NavisworksTransport.Core.Config
}
}
/// <summary>
/// 配置变更事件
/// 订阅此事件以在配置发生变化时接收通知
/// </summary>
public event EventHandler<ConfigurationChangedEventArgs> ConfigurationChanged;
/// <summary>
/// 特定类别配置变更事件
/// 参数:发送者,(类别,事件参数)
/// </summary>
public event EventHandler<Tuple<ConfigCategory, ConfigurationChangedEventArgs>> CategoryConfigurationChanged;
/// <summary>
/// 配置文件路径
/// </summary>
@ -78,10 +135,124 @@ namespace NavisworksTransport.Core.Config
private SystemConfig _currentConfig;
private string _cachedTemplateContent;
private FileSystemWatcher _fileWatcher;
private bool _isDisposed;
private bool _isReloading;
private DateTime _lastWriteTime;
private readonly object _reloadLock = new object();
/// <summary>
/// 是否启用文件监控(自动检测外部配置修改)
/// 默认启用
/// </summary>
public bool EnableFileWatcher { get; set; } = true;
/// <summary>
/// 文件监控防抖时间(毫秒)
/// 防止文件保存时多次触发事件
/// </summary>
public int FileWatcherDebounceMs { get; set; } = 500;
private ConfigManager()
{
_currentConfig = LoadConfigFile();
InitializeFileWatcher();
}
/// <summary>
/// 初始化文件监控
/// </summary>
private void InitializeFileWatcher()
{
try
{
if (!EnableFileWatcher)
{
LogManager.Debug("配置文件监控已禁用");
return;
}
string configDir = ConfigDirectory;
if (!Directory.Exists(configDir))
{
Directory.CreateDirectory(configDir);
}
_fileWatcher = new FileSystemWatcher(configDir, "config.toml")
{
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
EnableRaisingEvents = true
};
_fileWatcher.Changed += OnConfigFileChanged;
_fileWatcher.Renamed += OnConfigFileRenamed;
LogManager.Info($"配置文件监控已启动: {ConfigFilePath}");
}
catch (Exception ex)
{
LogManager.Error($"初始化配置文件监控失败: {ex.Message}");
// 不影响主功能,继续运行
}
}
/// <summary>
/// 配置文件变化处理
/// </summary>
private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
{
if (_isReloading || e.ChangeType != WatcherChangeTypes.Changed)
return;
lock (_reloadLock)
{
try
{
// 防抖处理:检查文件最后写入时间
var fileInfo = new FileInfo(e.FullPath);
if ((DateTime.Now - fileInfo.LastWriteTime).TotalMilliseconds > FileWatcherDebounceMs)
{
return;
}
// 避免重复加载
if ((DateTime.Now - _lastWriteTime).TotalMilliseconds < FileWatcherDebounceMs)
{
return;
}
_isReloading = true;
_lastWriteTime = DateTime.Now;
LogManager.Info("检测到配置文件外部修改,正在重新加载...");
// 延迟一点执行,确保文件写入完成
System.Threading.Thread.Sleep(100);
// 重新加载配置
ReloadInternal(isExternal: true);
}
catch (Exception ex)
{
LogManager.Error($"处理配置文件变更失败: {ex.Message}");
}
finally
{
_isReloading = false;
}
}
}
/// <summary>
/// 配置文件重命名处理
/// </summary>
private void OnConfigFileRenamed(object sender, RenamedEventArgs e)
{
if (e.Name == "config.toml")
{
LogManager.Info("配置文件被重命名/恢复,正在重新加载...");
ReloadInternal(isExternal: true);
}
}
/// <summary>
@ -259,6 +430,16 @@ namespace NavisworksTransport.Core.Config
/// 保存配置到文件
/// </summary>
public void SaveConfig(SystemConfig config)
{
SaveConfig(config, notifyChange: true);
}
/// <summary>
/// 保存配置到文件
/// </summary>
/// <param name="config">配置对象</param>
/// <param name="notifyChange">是否触发配置变更事件</param>
public void SaveConfig(SystemConfig config, bool notifyChange)
{
try
{
@ -270,6 +451,12 @@ namespace NavisworksTransport.Core.Config
_currentConfig = config;
LogManager.Info($"配置文件已保存: {ConfigFilePath}");
// 触发配置变更事件
if (notifyChange)
{
NotifyConfigurationChanged(ConfigCategory.All, isExternal: false);
}
}
catch (Exception ex)
{
@ -397,7 +584,28 @@ namespace NavisworksTransport.Core.Config
/// </summary>
public void Reload()
{
_currentConfig = LoadConfigFile();
ReloadInternal(isExternal: false);
}
/// <summary>
/// 内部重新加载方法
/// </summary>
/// <param name="isExternal">是否是外部修改触发的重载</param>
private void ReloadInternal(bool isExternal)
{
try
{
_currentConfig = LoadConfigFile();
LogManager.Info($"配置文件已重新加载{(isExternal ? "" : "")}");
// 触发配置变更事件
NotifyConfigurationChanged(ConfigCategory.All, isExternal);
}
catch (Exception ex)
{
LogManager.Error($"重新加载配置文件失败: {ex.Message}");
throw;
}
}
/// <summary>
@ -418,6 +626,73 @@ namespace NavisworksTransport.Core.Config
_currentConfig = newConfig;
LogManager.Info("默认配置恢复完成");
// 触发配置变更事件
NotifyConfigurationChanged(ConfigCategory.All, isExternal: false);
}
/// <summary>
/// 触发配置变更事件
/// </summary>
/// <param name="category">变更的配置类别</param>
/// <param name="isExternal">是否是外部修改</param>
public void NotifyConfigurationChanged(ConfigCategory category, bool isExternal = false)
{
var args = new ConfigurationChangedEventArgs(category, isExternal);
try
{
// 触发总事件
ConfigurationChanged?.Invoke(this, args);
// 触发分类事件
CategoryConfigurationChanged?.Invoke(this,
new Tuple<ConfigCategory, ConfigurationChangedEventArgs>(category, args));
// 如果是 All触发各个分类事件
if (category == ConfigCategory.All)
{
for (int i = 1; i <= 7; i++)
{
CategoryConfigurationChanged?.Invoke(this,
new Tuple<ConfigCategory, ConfigurationChangedEventArgs>((ConfigCategory)i, args));
}
}
LogManager.Debug($"配置变更事件已触发: {category}");
}
catch (Exception ex)
{
LogManager.Error($"触发配置变更事件失败: {ex.Message}");
}
}
/// <summary>
/// 更新特定类别的配置并触发事件
/// </summary>
/// <param name="category">配置类别</param>
/// <param name="updateAction">更新操作</param>
public void UpdateCategoryConfig(ConfigCategory category, Action<SystemConfig> updateAction)
{
if (updateAction == null)
throw new ArgumentNullException(nameof(updateAction));
updateAction(_currentConfig);
SaveConfig(_currentConfig, notifyChange: false);
NotifyConfigurationChanged(category, isExternal: false);
}
/// <summary>
/// 资源释放
/// </summary>
public void Dispose()
{
if (!_isDisposed)
{
_fileWatcher?.Dispose();
_isDisposed = true;
LogManager.Info("ConfigManager 已释放");
}
}
// 辅助方法:从 TomlTable 获取必需值

View File

@ -9,6 +9,7 @@ using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Models;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Commands;
using NavisworksTransport.UI.WPF.Collections;
using NavisworksTransport.Utils;
@ -939,7 +940,95 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 设置动画按钮的初始状态
UpdateAnimationButtonStates();
LogManager.Info($"动画设置初始化完成 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒, 安全间隙:{_safetyMargin}米"); }
LogManager.Info($"动画设置初始化完成 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒, 安全间隙:{_safetyMargin}米");
// 订阅配置变更事件
SubscribeToConfigChanges();
}
#region
/// <summary>
/// 订阅配置变更事件
/// </summary>
private void SubscribeToConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged;
LogManager.Info("AnimationControlViewModel 已订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅配置变更事件
/// </summary>
private void UnsubscribeFromConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged;
LogManager.Info("AnimationControlViewModel 已取消订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}");
}
}
/// <summary>
/// 配置变更事件处理
/// </summary>
private void OnCategoryConfigurationChanged(object sender, Tuple<ConfigCategory, ConfigurationChangedEventArgs> args)
{
try
{
var category = args.Item1;
var eventArgs = args.Item2;
// 处理 Animation 类别变更
if (category == ConfigCategory.Animation || category == ConfigCategory.All)
{
LogManager.Info("收到 Animation 配置变更通知,正在更新参数...");
var config = ConfigManager.Instance.Current;
// 更新动画参数
SelectedFrameRate = config.Animation.FrameRate;
AnimationDuration = config.Animation.DurationSeconds;
AnimationFrameRate = config.Animation.FrameRate;
_detectionTolerance = config.Animation.DetectionToleranceMeters;
LogManager.Info($"Animation 配置已更新 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒");
}
// 处理 PathEditing 类别变更(车辆参数和安全间隙)
if (category == ConfigCategory.PathEditing || category == ConfigCategory.All)
{
LogManager.Info("收到 PathEditing 配置变更通知,正在更新车辆参数...");
var config = ConfigManager.Instance.Current;
// 更新车辆参数
VirtualVehicleLength = config.PathEditing.VehicleLengthMeters;
VirtualVehicleWidth = config.PathEditing.VehicleWidthMeters;
VirtualVehicleHeight = config.PathEditing.VehicleHeightMeters;
_safetyMargin = config.PathEditing.SafetyMarginMeters;
LogManager.Info($"车辆参数已更新 - 尺寸:{VirtualVehicleLength:F1}x{VirtualVehicleWidth:F1}x{VirtualVehicleHeight:F1}米, 安全间隙:{_safetyMargin:F2}米");
}
}
catch (Exception ex)
{
LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex);
}
}
#endregion
/// <summary>
/// 初始化命令
@ -3351,6 +3440,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 1. 取消事件订阅(在停止动画之前,避免事件处理中访问已释放的对象)
// 取消配置变更事件订阅
UnsubscribeFromConfigChanges();
// 取消DocumentStateManager事件订阅
try
{

View File

@ -392,6 +392,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 初始化命令
InitializeCommands();
// 订阅配置变更事件
SubscribeToConfigChanges();
// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
SubscribeToSelectionEvents();
@ -414,6 +417,84 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#endregion
#region
/// <summary>
/// 订阅配置变更事件
/// </summary>
private void SubscribeToConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged;
LogManager.Info("ModelSettingsViewModel 已订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅配置变更事件
/// </summary>
private void UnsubscribeFromConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged;
LogManager.Info("ModelSettingsViewModel 已取消订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}");
}
}
/// <summary>
/// 配置变更事件处理
/// </summary>
private void OnCategoryConfigurationChanged(object sender, Tuple<ConfigCategory, ConfigurationChangedEventArgs> args)
{
try
{
var category = args.Item1;
var eventArgs = args.Item2;
// 处理 Logistics 类别变更
if (category == ConfigCategory.Logistics || category == ConfigCategory.All)
{
LogManager.Info("收到 Logistics 配置变更通知,正在更新默认属性值...");
var config = ConfigManager.Instance.Current;
// 更新默认属性值(仅当用户未选择模型时)
SafeExecute(() =>
{
// 如果当前没有选择模型,更新默认值
if (!HasSelectedModels)
{
IsTraversable = config.Logistics.Traversable;
Priority = config.Logistics.Priority;
WidthLimit = config.Logistics.WidthLimitMeters;
HeightLimit = config.Logistics.HeightLimitMeters;
SpeedLimit = config.Logistics.SpeedLimitMetersPerSecond;
string source = eventArgs.IsExternalChange ? "外部修改" : "内部更新";
UpdateMainStatus($"默认属性已更新 ({source})");
LogManager.Info($"默认物流属性已更新 - 来源: {source}");
}
});
}
}
catch (Exception ex)
{
LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex);
}
}
#endregion
#region - Command Pattern
/// <summary>
@ -1368,6 +1449,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 取消文档模型集合事件订阅
UnsubscribeFromDocumentModelsEvents();
// 取消配置变更事件订阅
UnsubscribeFromConfigChanges();
LogManager.Info("[ModelSettingsViewModel] 资源清理完成");
}
catch (Exception ex)

View File

@ -735,6 +735,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 从配置加载参数
LoadParametersFromConfig();
// 订阅配置变更事件
SubscribeToConfigChanges();
// 初始化命令
InitializeCommands();
@ -815,6 +818,86 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
#region
/// <summary>
/// 订阅配置变更事件
/// </summary>
private void SubscribeToConfigChanges()
{
try
{
// 订阅特定类别的配置变更事件
ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged;
LogManager.Info("PathEditingViewModel 已订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅配置变更事件
/// </summary>
private void UnsubscribeFromConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged;
LogManager.Info("PathEditingViewModel 已取消订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}");
}
}
/// <summary>
/// 配置变更事件处理
/// </summary>
private void OnCategoryConfigurationChanged(object sender, Tuple<ConfigCategory, ConfigurationChangedEventArgs> args)
{
try
{
var category = args.Item1;
var eventArgs = args.Item2;
// 只处理 PathEditing 相关的配置变更
if (category == ConfigCategory.PathEditing || category == ConfigCategory.All)
{
LogManager.Info($"收到 PathEditing 配置变更通知,正在更新参数...");
// 从配置重新加载参数
LoadParametersFromConfig();
// 触发属性变更通知更新UI
OnPropertiesChanged(
nameof(VehicleLength),
nameof(VehicleWidth),
nameof(VehicleHeight),
nameof(SafetyMargin),
nameof(GridSize)
);
// 同步车辆参数到渲染插件
SyncVehicleParametersToRenderPlugin();
// 更新状态栏
string source = eventArgs.IsExternalChange ? "外部修改" : "内部更新";
UpdateMainStatus($"配置已更新 ({source}) - 车辆参数: {VehicleLength:F1}x{VehicleWidth:F1}x{VehicleHeight:F1}米");
LogManager.Info($"PathEditing 配置参数已更新完成 - 来源: {source}");
}
}
catch (Exception ex)
{
LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex);
}
}
#endregion
private void InitializeCommands()
{
NewPathCommand = new RelayCommand(async () => await ExecuteNewPathAsync(), () => CanExecuteNewPath);
@ -3564,6 +3647,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
LogManager.Info("开始清理PathEditingViewModel资源");
// 取消配置变更事件订阅
UnsubscribeFromConfigChanges();
// 取消事件订阅
UnsubscribeFromPathPlanningManager();

View File

@ -134,6 +134,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
InitializeCollections();
LoadRouteData(_pathPlanningManager.CurrentRoute);
// 订阅配置变更事件
SubscribeToConfigChanges();
LogManager.Info($"TimeTagViewModel初始化完成 - 默认速度: {_defaultSpeed:F1}m/s来自配置");
}
catch (Exception ex)
@ -142,6 +145,75 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
#region
/// <summary>
/// 订阅配置变更事件
/// </summary>
private void SubscribeToConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged += OnCategoryConfigurationChanged;
LogManager.Info("TimeTagViewModel 已订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Error($"订阅配置变更事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅配置变更事件
/// </summary>
private void UnsubscribeFromConfigChanges()
{
try
{
ConfigManager.Instance.CategoryConfigurationChanged -= OnCategoryConfigurationChanged;
LogManager.Info("TimeTagViewModel 已取消订阅配置变更事件");
}
catch (Exception ex)
{
LogManager.Warning($"取消订阅配置变更事件时发生异常: {ex.Message}");
}
}
/// <summary>
/// 配置变更事件处理
/// </summary>
private void OnCategoryConfigurationChanged(object sender, Tuple<ConfigCategory, ConfigurationChangedEventArgs> args)
{
try
{
var category = args.Item1;
var eventArgs = args.Item2;
// 处理 Logistics 类别变更(默认速度)
if (category == ConfigCategory.Logistics || category == ConfigCategory.All)
{
LogManager.Info("收到 Logistics 配置变更通知,正在更新默认速度...");
var config = ConfigManager.Instance.Current;
double newSpeed = config.Logistics.SpeedLimitMetersPerSecond;
// 更新默认速度
if (_defaultSpeed != newSpeed)
{
_defaultSpeed = newSpeed;
DefaultSpeed = newSpeed; // 触发属性变更通知
LogManager.Info($"默认速度已更新: {newSpeed:F1} m/s");
}
}
}
catch (Exception ex)
{
LogManager.Error($"处理配置变更事件失败: {ex.Message}", ex);
}
}
#endregion
#endregion
#region
@ -438,6 +510,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
#endregion
#region
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
UnsubscribeFromConfigChanges();
}
#endregion
}
#region