using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Threading.Tasks; using System.Linq; using NavisworksTransport.Core; namespace NavisworksTransport.UI.WPF.ViewModels { /// /// 路径点数据类 (UI ViewModel) /// 已重构为线程安全的ViewModel,继承自ViewModelBase /// public class PathPointViewModel : ViewModelBase { private string _id; private double _x; private double _y; private double _z; private string _name; private NavisworksTransport.PathPointType _type; // 使用完全限定名 private int _index; // 路径点在列表中的索引 /// /// 路径点ID /// public string Id { get => _id; set => SetProperty(ref _id, value); } /// /// X坐标 /// public double X { get => _x; set { if (SetProperty(ref _x, value)) { OnPropertyChanged(nameof(CoordinateString)); } } } /// /// Y坐标 /// public double Y { get => _y; set { if (SetProperty(ref _y, value)) { OnPropertyChanged(nameof(CoordinateString)); } } } /// /// Z坐标 /// public double Z { get => _z; set { if (SetProperty(ref _z, value)) { OnPropertyChanged(nameof(CoordinateString)); } } } /// /// 点名称 /// public string Name { get => _name; set => SetProperty(ref _name, value); } /// /// 点类型 /// public NavisworksTransport.PathPointType Type // 使用完全限定名 { get => _type; set { if (SetProperty(ref _type, value)) { // 当Type变更时,自动触发TypeDisplayString的更新 OnPropertyChanged(nameof(TypeDisplayString)); } } } /// /// 点类型的显示字符串 /// public string TypeDisplayString { get { switch (Type) { case NavisworksTransport.PathPointType.StartPoint: return "起点"; case NavisworksTransport.PathPointType.EndPoint: return "终点"; default: return "途经点"; } } } /// /// 路径点在列表中的索引 /// public int Index { get => _index; set => SetProperty(ref _index, value); } /// /// 坐标字符串表示 /// public string CoordinateString => $"({X:F2}, {Y:F2}, {Z:F2})"; #region 构造函数 /// /// 初始化PathPointViewModel /// public PathPointViewModel() : base() { // 设置默认值 _id = Guid.NewGuid().ToString(); _name = "路径点"; _type = NavisworksTransport.PathPointType.WayPoint; _x = 0.0; _y = 0.0; _z = 0.0; } /// /// 使用指定参数初始化PathPointViewModel /// /// 点名称 /// X坐标 /// Y坐标 /// Z坐标 /// 点类型 public PathPointViewModel(string name, double x, double y, double z, NavisworksTransport.PathPointType type = NavisworksTransport.PathPointType.WayPoint) : base() { _id = Guid.NewGuid().ToString(); _name = name ?? "路径点"; _x = x; _y = y; _z = z; _type = type; } #endregion } /// /// 路径视图模型类 - 用于WPF数据绑定 /// 已重构为线程安全的ViewModel,集成UIStateManager和ThreadSafeObservableCollection /// public class PathRouteViewModel : ViewModelBase { #region 私有字段 private PathRoute _route; // 核心路径对象引用 private string _id; private string _name; private ObservableCollection _points; private bool _isActive; private string _description; private DateTime _createdTime; private DateTime _lastModifiedTime; private bool _isValidated; private string _validationStatus; private PathType _pathType; // UI状态管理 private readonly UIStateManager _uiStateManager; private bool _isInitialized = false; #endregion #region 公共属性 /// /// 核心路径对象(直接引用,避免数据重复) /// public PathRoute Route { get => _route; set { if (SetProperty(ref _route, value)) { // Route变化时,通知所有从Route读取的属性更新 OnPropertyChanged(nameof(Id)); OnPropertyChanged(nameof(Name)); OnPropertyChanged(nameof(Description)); OnPropertyChanged(nameof(PathType)); OnPropertyChanged(nameof(TotalLength)); OnPropertyChanged(nameof(CreatedTime)); OnPropertyChanged(nameof(LastModifiedTime)); } } } /// /// 路径ID /// public string Id { get => Route?.Id ?? _id; set => SetProperty(ref _id, value); } /// /// 路径名称 /// public string Name { get => Route?.Name ?? _name; set { if (SetProperty(ref _name, value)) { _lastModifiedTime = DateTime.Now; OnPropertyChanged(nameof(LastModifiedTime)); } } } /// /// 路径点集合 /// public ObservableCollection Points { get => _points; private set => SetProperty(ref _points, value); } /// /// 是否为活动路径 /// public bool IsActive { get => _isActive; set { if (SetProperty(ref _isActive, value)) { _lastModifiedTime = DateTime.Now; OnPropertyChanged(nameof(LastModifiedTime)); OnPropertyChanged(nameof(StatusString)); } } } /// /// 路径描述 /// public string Description { get => Route?.Description ?? _description; set { if (SetProperty(ref _description, value)) { _lastModifiedTime = DateTime.Now; OnPropertyChanged(nameof(LastModifiedTime)); } } } /// /// 路径点数量 /// public int PointCount => Points?.Count ?? 0; /// /// 路径类型 /// public NavisworksTransport.PathType PathType { get => Route?.PathType ?? _pathType; set => SetProperty(ref _pathType, value); } /// /// 空中路径子类型(仅当 PathType == Aerial 时有效) /// public NavisworksTransport.AerialSubType AerialSubType { get; set; } = NavisworksTransport.AerialSubType.Rail; /// /// 创建时间 /// public DateTime CreatedTime { get => Route?.CreatedTime ?? _createdTime; private set => SetProperty(ref _createdTime, value); } /// /// 最后修改时间 /// public DateTime LastModifiedTime { get => Route?.LastModified ?? _lastModifiedTime; private set => SetProperty(ref _lastModifiedTime, value); } /// /// 设置时间信息(用于从数据库加载) /// public void SetTimeInfo(DateTime createdTime, DateTime lastModifiedTime) { _createdTime = createdTime; _lastModifiedTime = lastModifiedTime; OnPropertyChanged(nameof(CreatedTime)); OnPropertyChanged(nameof(LastModifiedTime)); } /// /// 路径总长度(米) /// public double TotalLength { get => Route?.TotalLength ?? 0.0; } /// /// 是否已验证 /// public bool IsValidated { get => _isValidated; private set => SetProperty(ref _isValidated, value); } /// /// 验证状态描述 /// public string ValidationStatus { get => _validationStatus; private set => SetProperty(ref _validationStatus, value); } /// /// 路径状态字符串 /// public string StatusString => IsActive ? "活动" : "非活动"; /// /// 路径摘要信息 /// public string SummaryInfo => $"{Name} - {PointCount}个点 - {TotalLength:F2}m - {StatusString}"; /// /// 是否已初始化 /// public bool IsInitialized => _isInitialized; #endregion #region 构造函数和初始化 /// /// 默认构造函数(用于新建路径) /// public PathRouteViewModel() : this(isFromDatabase: false) { } /// /// 构造函数,控制是否从数据库加载 /// /// 是否从数据库/内存加载(false表示新建路径) public PathRouteViewModel(bool isFromDatabase) { try { // 获取UI状态管理器实例 _uiStateManager = UIStateManager.Instance; // 验证关键组件 if (_uiStateManager == null) { LogManager.Error("UIStateManager初始化失败"); throw new InvalidOperationException("UIStateManager初始化失败"); } // 根据场景选择初始化方式 if (!isFromDatabase) { InitializeDefaultsForNewRoute(); } else { InitializeMinimal(); } // 直接完成初始化,不需要异步 CompleteInitialization(); LogManager.Debug($"PathRouteViewModel构造函数完成:{_name}"); } catch (Exception ex) { LogManager.Error($"PathRouteViewModel构造函数异常: {ex.Message}", ex); throw; } } /// /// 使用指定名称构造(用于新建路径) /// /// 路径名称 public PathRouteViewModel(string name) : this() { _name = name ?? "新路径"; } /// /// 使用完整参数构造(用于新建路径) /// /// 路径名称 /// 路径描述 public PathRouteViewModel(string name, string description) : this() { _name = name ?? "新路径"; _description = description ?? ""; } /// /// 最小化初始化(用于从数据库/内存加载路径) /// private void InitializeMinimal() { _id = string.Empty; _name = string.Empty; _description = string.Empty; _isActive = false; _createdTime = DateTime.MinValue; _lastModifiedTime = DateTime.MinValue; _isValidated = false; _validationStatus = "未验证"; // 初始化点集合 Points = new ObservableCollection(); } /// /// 初始化默认值(用于新建路径) /// private void InitializeDefaultsForNewRoute() { _id = Guid.NewGuid().ToString(); _name = "新路径"; _description = ""; _isActive = false; _createdTime = DateTime.Now; _lastModifiedTime = DateTime.Now; _isValidated = false; _validationStatus = "未验证"; // 初始化点集合 Points = new ObservableCollection(); } /// /// 完成初始化 /// private void CompleteInitialization() { try { // 订阅Points集合变更事件 if (Points != null) { Points.CollectionChanged += OnPointsCollectionChanged; } // 设置初始化完成标志 _isInitialized = true; OnPropertyChanged(nameof(IsInitialized)); LogManager.Debug($"PathRouteViewModel初始化完成:{_name}"); } catch (Exception ex) { LogManager.Error($"PathRouteViewModel初始化异常: {ex.Message}", ex); } } /// /// 异步初始化方法(保留用于向后兼容) /// /// 异步任务 [Obsolete("已改为同步初始化,此方法保留用于向后兼容")] public async Task InitializeAsync() { await Task.CompletedTask; // 现在初始化已经在构造函数中同步完成 } /// /// 处理Points集合变更事件 /// private void OnPointsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { SafeExecute(() => { // 通知相关属性变更 OnPropertyChanged(nameof(PointCount)); OnPropertyChanged(nameof(SummaryInfo)); // TotalLength直接从Route读取,不需要手动通知 // 更新最后修改时间 _lastModifiedTime = DateTime.Now; OnPropertyChanged(nameof(LastModifiedTime)); // 标记为未验证 if (_isValidated) { _isValidated = false; _validationStatus = "需要重新验证"; OnPropertyChanged(nameof(IsValidated)); OnPropertyChanged(nameof(ValidationStatus)); } }, "处理Points集合变更"); } #endregion #region 业务方法 /// /// 异步添加路径点 /// /// 要添加的路径点 /// 异步任务 public async Task AddPointAsync(PathPointViewModel point) { if (point == null) { throw new ArgumentNullException(nameof(point)); } await SafeExecuteAsync(async () => { await _uiStateManager.ExecuteUIUpdateAsync(() => { Points.Add(point); LogManager.Debug($"添加路径点:{point.Name} 到路径 {_name}"); }); }, "添加路径点"); } /// /// 异步批量添加路径点 /// /// 要添加的路径点集合 /// 异步任务 public async Task AddPointsAsync(IEnumerable points) { if (points == null) { throw new ArgumentNullException(nameof(points)); } var pointList = points.ToList(); if (pointList.Count == 0) { return; } await SafeExecuteAsync(async () => { await _uiStateManager.ExecuteUIUpdateAsync(() => { foreach (var point in pointList) { Points.Add(point); } LogManager.Debug($"批量添加{pointList.Count}个路径点到路径 {_name}"); }); }, "批量添加路径点"); } /// /// 异步移除路径点 /// /// 要移除的路径点 /// 是否成功移除 public async Task RemovePointAsync(PathPointViewModel point) { if (point == null) { return false; } try { return await _uiStateManager.ExecuteUIUpdateAsync(() => { bool removed = Points.Remove(point); if (removed) { LogManager.Debug($"移除路径点:{point.Name} 从路径 {_name}"); } return removed; }); } catch (Exception ex) { LogManager.Error($"移除路径点失败: {ex.Message}"); return false; } } /// /// 异步清空所有路径点 /// /// 异步任务 public async Task ClearPointsAsync() { await SafeExecuteAsync(async () => { await _uiStateManager.ExecuteUIUpdateAsync(() => { var count = Points.Count; Points.Clear(); LogManager.Debug($"清空路径 {_name} 的所有路径点,共{count}个"); }); }, "清空路径点"); } /// /// 异步验证路径有效性 /// /// 验证结果 public async Task ValidateAsync() { try { // 先在UI线程上创建快照,确保线程安全 var pointsSnapshot = await _uiStateManager.ExecuteUIUpdateAsync(() => { return Points?.ToList() ?? new List(); }); var nameSnapshot = await _uiStateManager.ExecuteUIUpdateAsync(() => _name); // 然后在后台线程验证 return await Task.Run(() => { bool isValid = true; var validationMessages = new List(); // 检查路径点数量 if (pointsSnapshot.Count < 2) { isValid = false; validationMessages.Add("路径至少需要2个点"); } // 检查路径名称 if (string.IsNullOrWhiteSpace(nameSnapshot)) { isValid = false; validationMessages.Add("路径名称不能为空"); } // 检查重复点 var duplicatePoints = pointsSnapshot .GroupBy(p => new { p.X, p.Y, p.Z }) .Where(g => g.Count() > 1) .ToList(); if (duplicatePoints.Any()) { isValid = false; validationMessages.Add($"发现{duplicatePoints.Count}组重复坐标的点"); } // 在UI线程上更新验证状态 _uiStateManager.QueueUIUpdate(() => { _isValidated = true; _validationStatus = isValid ? "验证通过" : string.Join("; ", validationMessages); OnPropertyChanged(nameof(IsValidated)); OnPropertyChanged(nameof(ValidationStatus)); }); LogManager.Debug($"路径验证完成:{nameSnapshot},结果:{(isValid ? "通过" : "失败")}"); return isValid; }); } catch (Exception ex) { LogManager.Error($"验证路径失败: {ex.Message}"); return false; } } /// /// 获取指定索引的路径点 /// /// 索引 /// 路径点,如果索引无效返回null public PathPointViewModel GetPointAt(int index) { return SafeExecute(() => { if (index >= 0 && index < Points.Count) { return Points[index]; } return null; }, null, "获取指定索引路径点"); } /// /// 查找指定名称的路径点 /// /// 点名称 /// 匹配的路径点,如果未找到返回null public PathPointViewModel FindPoint(string name) { if (string.IsNullOrEmpty(name)) { return null; } return SafeExecute(() => { return Points.FirstOrDefault(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase)); }, null, "查找路径点"); } #endregion #region 向后兼容性接口 /// /// 向后兼容:同步版本的添加点方法 /// /// 要添加的路径点 [Obsolete("请使用AddPointAsync方法以获得更好的性能", false)] public void AddPoint(PathPointViewModel point) { _ = AddPointAsync(point); } /// /// 向后兼容:同步版本的移除点方法 /// /// 要移除的路径点 /// 是否成功移除 [Obsolete("请使用RemovePointAsync方法以获得更好的性能", false)] public bool RemovePoint(PathPointViewModel point) { return RemovePointAsync(point).Result; } /// /// 向后兼容:同步版本的清空方法 /// [Obsolete("请使用ClearPointsAsync方法以获得更好的性能", false)] public void ClearPoints() { _ = ClearPointsAsync(); } /// /// 向后兼容:提供ObservableCollection接口 /// [Obsolete("直接使用Points属性,它已经是线程安全的ThreadSafeObservableCollection", false)] public ObservableCollection GetPointsAsObservableCollection() { // 返回原始的ThreadSafeObservableCollection,它继承自ObservableCollection return Points; } /// /// 验证ViewModel状态是否正常 /// /// 是否处于有效状态 public bool IsValidState() { return _uiStateManager != null && Points != null && _isInitialized; } /// /// 获取ViewModel状态信息 /// /// 状态描述字符串 public string GetStateInfo() { return $"名称: {_name}, " + $"点数量: {Points?.Count ?? 0}, " + $"活动状态: {_isActive}, " + $"已初始化: {_isInitialized}, " + $"验证状态: {_validationStatus}"; } #endregion } }