using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NavisworksTransport.Core;
using NavisworksTransport.UI.WPF.Services;
using NavisworksTransport.UI.WPF.Interfaces;
namespace NavisworksTransport.UI.WPF.ViewModels
{
///
/// ViewModel基类,实现INotifyPropertyChanged接口
/// 集成UIStateManager提供线程安全的属性更新和防重入机制
/// 集成智能数据绑定优化功能,支持延迟更新、批量更新和条件更新
///
public abstract class ViewModelBase : IPropertyChangeNotifier
{
#region 字段和属性
public event PropertyChangedEventHandler PropertyChanged;
///
/// UI状态管理器,提供线程安全的UI更新机制
///
private readonly UIStateManager _uiStateManager;
///
/// 智能数据绑定优化器,提供延迟更新、批量更新等优化功能
///
private readonly SmartDataBindingOptimizer _bindingOptimizer;
///
/// 正在更新的属性集合,用于防重入检测
///
private readonly HashSet _updatingProperties = new HashSet();
///
/// 属性更新锁,确保线程安全
///
private readonly object _propertyLock = new object();
///
/// 是否启用智能优化功能
///
protected bool IsSmartOptimizationEnabled { get; set; } = true;
///
/// 主ViewModel引用,用于统一状态栏更新
///
protected LogisticsControlViewModel _mainViewModel;
#endregion
#region 构造函数
///
/// 初始化ViewModelBase
///
protected ViewModelBase()
{
_uiStateManager = UIStateManager.Instance;
_bindingOptimizer = SmartDataBindingOptimizer.Instance;
}
#endregion
#region 属性更新方法
///
/// 触发属性变更通知(线程安全,防重入)
///
/// 属性名称,自动获取调用者名称
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (string.IsNullOrEmpty(propertyName))
{
return;
}
try
{
// 防重入检查
lock (_propertyLock)
{
if (_updatingProperties.Contains(propertyName))
{
// 属性正在更新中,防止重入
LogManager.Debug($"[ViewModel] 检测到属性重入更新,跳过: {propertyName}");
return;
}
// 标记属性为正在更新状态
_updatingProperties.Add(propertyName);
}
// 使用UIStateManager确保在UI线程上安全执行
if (_uiStateManager.IsUIThread)
{
// 已在UI线程上,直接触发
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
else
{
// 异步切换到UI线程执行
_ = _uiStateManager.ExecuteUIUpdateAsync(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
});
}
}
catch (Exception ex)
{
LogManager.Error($"[ViewModel] OnPropertyChanged失败: {ex.Message},属性: {propertyName}");
}
finally
{
// 清除更新标记
lock (_propertyLock)
{
_updatingProperties.Remove(propertyName);
}
}
}
///
/// 公共接口:触发指定属性的变更通知(供外部组件使用,替代反射调用)
///
/// 属性名称
public virtual void NotifyPropertyChanged(string propertyName)
{
OnPropertyChanged(propertyName);
}
///
/// 同步触发属性变更通知(确保在UI线程上执行完成)
///
/// 属性名称
/// 超时时间(毫秒),默认3000ms
protected virtual async Task OnPropertyChangedAsync(string propertyName, int timeout = 3000)
{
if (string.IsNullOrEmpty(propertyName))
{
return;
}
// 防重入检查
lock (_propertyLock)
{
if (_updatingProperties.Contains(propertyName))
{
LogManager.Debug($"[ViewModel] 检测到属性重入更新,跳过: {propertyName}");
return;
}
_updatingProperties.Add(propertyName);
}
try
{
// 使用UIStateManager确保同步执行
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}, timeout);
}
catch (Exception ex)
{
LogManager.Error($"[ViewModel] OnPropertyChangedAsync失败: {ex.Message},属性: {propertyName}");
throw;
}
finally
{
lock (_propertyLock)
{
_updatingProperties.Remove(propertyName);
}
}
}
///
/// 批量触发属性变更通知(原子性操作)
///
/// 要更新的属性名称数组
public virtual void OnPropertiesChanged(params string[] propertyNames)
{
if (propertyNames == null || propertyNames.Length == 0)
{
return;
}
// 去重并过滤空值
var uniqueProperties = propertyNames.Where(p => !string.IsNullOrEmpty(p)).Distinct().ToArray();
if (uniqueProperties.Length == 0)
{
return;
}
// 防重入检查
var propertiesToUpdate = new List();
lock (_propertyLock)
{
foreach (var propertyName in uniqueProperties)
{
if (!_updatingProperties.Contains(propertyName))
{
_updatingProperties.Add(propertyName);
propertiesToUpdate.Add(propertyName);
}
else
{
LogManager.Debug($"[ViewModel] 检测到属性重入更新,跳过: {propertyName}");
}
}
}
if (propertiesToUpdate.Count == 0)
{
return; // 所有属性都在更新中,避免重入
}
try
{
// 创建批量更新操作
var updateActions = propertiesToUpdate.Select(propertyName =>
new Action(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)))
).ToArray();
// 使用UIStateManager批量执行
_ = _uiStateManager.ExecuteBatchUIUpdate(updateActions);
}
catch (Exception ex)
{
LogManager.Error($"[ViewModel] OnPropertiesChanged失败: {ex.Message},属性: {string.Join(", ", propertiesToUpdate)}");
}
finally
{
// 清除所有更新标记
lock (_propertyLock)
{
foreach (var propertyName in propertiesToUpdate)
{
_updatingProperties.Remove(propertyName);
}
}
}
}
///
/// 批量设置属性值并触发变更通知(原子性操作)
///
/// 属性名称和值的键值对数组
protected virtual void SetProperties(params (string name, object value)[] properties)
{
if (properties == null || properties.Length == 0)
{
return;
}
try
{
// 批量更新操作
var updateActions = properties.Select(p =>
new Action(() => OnPropertyChanged(p.name))
).ToArray();
// 使用UIStateManager批量执行
_ = _uiStateManager.ExecuteBatchUIUpdate(updateActions);
}
catch (Exception ex)
{
LogManager.Error($"[ViewModel] SetProperties失败: {ex.Message}");
}
}
#endregion
#region 属性设置方法
///
/// 设置属性值并触发变更通知(线程安全)
///
/// 属性类型
/// 字段引用
/// 新值
/// 属性名称,自动获取调用者名称
/// 如果值发生变化返回true
protected bool SetProperty(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
///
/// 异步设置属性值并触发变更通知(确保UI线程同步执行)
///
/// 属性类型
/// 字段引用
/// 新值
/// 属性名称,自动获取调用者名称
/// 超时时间(毫秒),默认3000ms
/// 如果值发生变化返回true
protected async Task SetPropertyAsync(T field, T value, [CallerMemberName] string propertyName = null, int timeout = 3000)
{
if (EqualityComparer.Default.Equals(field, value))
return false;
await OnPropertyChangedAsync(propertyName, timeout);
return true;
}
///
/// 线程安全的属性设置方法(使用UIStateManager确保线程安全)
///
/// 属性类型
/// 字段引用
/// 新值
/// 属性名称,自动获取调用者名称
/// 如果值发生变化返回true
protected bool SetPropertyThreadSafe(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(field, value))
return false;
field = value;
// 使用UIStateManager确保在UI线程上触发属性变更通知
if (_uiStateManager.IsUIThread)
{
OnPropertyChanged(propertyName);
}
else
{
_ = _uiStateManager.ExecuteUIUpdateAsync(() => OnPropertyChanged(propertyName));
}
return true;
}
#endregion
#region 智能数据绑定优化方法
///
/// 延迟触发属性变更通知 - 将快速连续的更新合并为一次通知
///
/// 属性名称
/// 延迟间隔,null使用默认值
protected void OnPropertyChangedDelayed([CallerMemberName] string propertyName = null, TimeSpan? delayInterval = null)
{
if (!IsSmartOptimizationEnabled || string.IsNullOrEmpty(propertyName))
{
OnPropertyChanged(propertyName);
return;
}
_bindingOptimizer.RegisterDelayedUpdate(this, propertyName, () => OnPropertyChanged(propertyName), delayInterval);
}
///
/// 条件性触发属性变更通知 - 只有满足条件时才触发更新
///
/// 属性类型
/// 字段引用
/// 新值
/// 更新条件
/// 属性名称
/// 是否触发了更新
protected bool SetPropertyConditional(ref T field, T value, Func condition, [CallerMemberName] string propertyName = null)
{
if (condition != null && !condition(field, value))
return false;
return SetProperty(ref field, value, propertyName);
}
///
/// 设置属性值并支持智能优化
///
/// 属性类型
/// 字段引用
/// 新值
/// 更新模式
/// 属性名称
/// 是否发生了变化
public bool SetPropertySmart(ref T field, T value, PropertyUpdateMode updateMode = PropertyUpdateMode.Immediate, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(field, value))
return false;
var oldValue = field;
field = value;
switch (updateMode)
{
case PropertyUpdateMode.Immediate:
OnPropertyChanged(propertyName);
break;
case PropertyUpdateMode.Delayed:
OnPropertyChangedDelayed(propertyName);
break;
case PropertyUpdateMode.Conditional:
if (IsSmartOptimizationEnabled)
{
if (_bindingOptimizer.ShouldUpdateProperty(this, propertyName, oldValue, value))
{
OnPropertyChanged(propertyName);
}
}
else
{
OnPropertyChanged(propertyName);
}
break;
}
return true;
}
///
/// 开始批量属性更新 - 在作用域内的所有属性更新将被合并
///
/// 批量更新作用域
public IBatchUpdateScope BeginBatchUpdate()
{
if (!IsSmartOptimizationEnabled)
return new EmptyBatchScope();
return _bindingOptimizer.BeginBatchUpdate(this);
}
///
/// 配置属性的条件更新规则
///
/// 属性名称
/// 更新条件
/// 条件配置
public void ConfigurePropertyUpdate(string propertyName, Func