281 lines
10 KiB
C#
281 lines
10 KiB
C#
using UIShare.PubEvent;
|
||
using UIShare.UIViewModel;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Input;
|
||
using System.Xml;
|
||
using UIShare.GlobalVariable;
|
||
using UIShare.ViewModelBase;
|
||
using Prism.Events;
|
||
|
||
namespace TestingModule.ViewModels
|
||
{
|
||
public class StepsManagerViewModel:NavigateViewModelBase, IDisposable
|
||
{
|
||
#region 属性
|
||
private string _Title;
|
||
public string Title
|
||
{
|
||
get => _Title;
|
||
set => SetProperty(ref _Title, value);
|
||
}
|
||
private bool _Admin;
|
||
public bool Admin
|
||
{
|
||
get => _Admin;
|
||
set => SetProperty(ref _Admin, value);
|
||
}
|
||
private int _SelectedTabIndex;
|
||
public int SelectedTabIndex
|
||
{
|
||
get => _SelectedTabIndex;
|
||
set => SetProperty(ref _SelectedTabIndex, value);
|
||
}
|
||
private string _selectedTabHeader;
|
||
public string SelectedTabHeader
|
||
{
|
||
get { return _selectedTabHeader; }
|
||
set { SetProperty(ref _selectedTabHeader, value); }
|
||
}
|
||
private List<StepVM> _SelectedItems;
|
||
public List<StepVM> SelectedItems
|
||
{
|
||
get { return _SelectedItems; }
|
||
set { SetProperty(ref _SelectedItems, value); }
|
||
}
|
||
private StepVM _SelectedStep;
|
||
public StepVM SelectedStep
|
||
{
|
||
get => _SelectedStep;
|
||
set
|
||
{
|
||
if (SetProperty(ref _SelectedStep, value))
|
||
{
|
||
_ScopedContext.SelectedStep = value;
|
||
}
|
||
}
|
||
}
|
||
public ProgramVM Program
|
||
{
|
||
get => _ScopedContext.Program;
|
||
set
|
||
{
|
||
if (_ScopedContext.Program != value)
|
||
{
|
||
_ScopedContext.Program = value;
|
||
RaisePropertyChanged();
|
||
}
|
||
}
|
||
}
|
||
ScopedContext _ScopedContext { get; set; }
|
||
private readonly SystemConfig _systemConfig;
|
||
private readonly GlobalInfo _globalInfo;
|
||
private List<StepVM> tmpCopyList = new List<StepVM>();
|
||
|
||
|
||
#endregion
|
||
#region 命令
|
||
public ICommand EditStepCommand { get;set; }
|
||
public ICommand CopyStepCommand { get;set; }
|
||
public ICommand PasteStepCommand { get;set; }
|
||
public ICommand DeleteStepCommand { get;set; }
|
||
public ICommand TabSelectionChangedCommand { get;set; }
|
||
public ICommand SelectionChangedCommand { get;set; }
|
||
#endregion
|
||
|
||
public StepsManagerViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider)
|
||
{
|
||
_ScopedContext = scopedContext;
|
||
_systemConfig = systemConfig;
|
||
_globalInfo = globalInfo;
|
||
EditStepCommand = new DelegateCommand(EditStep);
|
||
CopyStepCommand = new DelegateCommand(CopyStep);
|
||
PasteStepCommand = new DelegateCommand(PasteStep);
|
||
DeleteStepCommand = new DelegateCommand(DeleteStep);
|
||
TabSelectionChangedCommand = new DelegateCommand<string>(TabSelectionChanged);
|
||
SelectionChangedCommand = new DelegateCommand<object>(SelectionChanged);
|
||
Program.StepCollection.CollectionChanged += StepCollection_CollectionChanged;
|
||
Program.ErrorStepCollection.CollectionChanged += StepCollection_CollectionChanged;
|
||
Admin = _globalInfo.IsAdmin;
|
||
_eventAggregator.GetEvent<AlarmEvent>().Subscribe(() =>
|
||
{
|
||
SelectedTabIndex = 1;
|
||
});
|
||
}
|
||
|
||
private void SelectionChanged(object parameter)
|
||
{
|
||
var selectedList = parameter as IList;
|
||
if (selectedList != null)
|
||
{
|
||
SelectedItems = selectedList.Cast<StepVM>().ToList();
|
||
}
|
||
}
|
||
|
||
private void TabSelectionChanged(string SelectedTabHeader)
|
||
{
|
||
_ScopedContext.SelectedStepList = SelectedTabHeader;
|
||
}
|
||
|
||
#region 委托命令
|
||
private void EditStep()
|
||
{
|
||
if (_globalInfo.IsAdmin && SelectedStep != null&& _ScopedContext.SelectedStep!=null)
|
||
{
|
||
_eventAggregator.GetEvent<EditSetpEvent>().Publish() ;
|
||
}
|
||
}
|
||
private void CopyStep()
|
||
{
|
||
if (_globalInfo.IsAdmin && SelectedItems.Any())
|
||
{
|
||
tmpCopyList.Clear();
|
||
foreach (var item in SelectedItems)
|
||
{
|
||
tmpCopyList.Add(item);
|
||
}
|
||
}
|
||
}
|
||
private void PasteStep()
|
||
{
|
||
// 权限校验并确保有可粘贴的内容
|
||
if (_globalInfo.IsAdmin && tmpCopyList.Any())
|
||
{
|
||
int insertIndex;
|
||
|
||
if (_ScopedContext.SelectedStepList == "主程序")
|
||
{
|
||
insertIndex = SelectedStep != null ? Program.StepCollection.IndexOf(SelectedStep) + 1 : Program.StepCollection.Count;
|
||
|
||
foreach (var item in tmpCopyList)
|
||
{
|
||
// 创建新副本,避免引用同一个对象,并赋予新 ID
|
||
var newStep = new StepVM(item) { ID = Guid.NewGuid() };
|
||
Program.StepCollection.Insert(insertIndex, newStep);
|
||
insertIndex++; // 递增索引,保证粘贴的多项顺序一致
|
||
}
|
||
}
|
||
else if (_ScopedContext.SelectedStepList == "错误程序")
|
||
{
|
||
insertIndex = SelectedStep != null ? Program.ErrorStepCollection.IndexOf(SelectedStep) + 1 : Program.ErrorStepCollection.Count;
|
||
|
||
foreach (var item in tmpCopyList)
|
||
{
|
||
var newStep = new StepVM(item) { ID = Guid.NewGuid() };
|
||
Program.ErrorStepCollection.Insert(insertIndex, newStep);
|
||
insertIndex++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
private void DeleteStep()
|
||
{
|
||
// 确保有选中的项
|
||
if (_globalInfo.IsAdmin && SelectedItems != null && SelectedItems.Any())
|
||
{
|
||
// 创建一个副本进行循环,防止在 Remove 过程中集合变化导致的问题
|
||
var toDelete = SelectedItems.ToList();
|
||
|
||
foreach (var item in toDelete)
|
||
{
|
||
_eventAggregator.GetEvent<DeletedStepEvent>().Publish(item.ID);
|
||
|
||
if (_ScopedContext.SelectedStepList == "主程序")
|
||
{
|
||
Program.StepCollection.Remove(item);
|
||
}
|
||
else if (_ScopedContext.SelectedStepList == "错误程序")
|
||
{
|
||
Program.ErrorStepCollection.Remove(item);
|
||
}
|
||
}
|
||
|
||
// 3. 清空 ViewModel 的选中状态,避免悬挂引用
|
||
SelectedStep = null;
|
||
SelectedItems.Clear();
|
||
_ScopedContext.SelectedStep = null;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 辅助方法
|
||
private void StepCollection_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||
{
|
||
var collection = sender as ObservableCollection<StepVM>;
|
||
// Add/Move/Remove 都会触发,这里判断具体情形
|
||
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
|
||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Move||
|
||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||
{
|
||
// 如果需要等 UI 更新完再处理,可也用 Dispatcher 延迟一小段时间
|
||
Application.Current?.Dispatcher.BeginInvoke(new Action(() =>
|
||
{
|
||
if(_ScopedContext.SelectedStepList=="主程序")
|
||
{
|
||
for (int i = 0; i < Program.StepCollection.Count; i++)
|
||
Program.StepCollection[i].Index = i + 1;
|
||
}
|
||
else if (_ScopedContext.SelectedStepList == "错误程序")
|
||
for (int i = 0; i < Program.ErrorStepCollection.Count; i++)
|
||
Program.ErrorStepCollection[i].Index = i + 1;
|
||
|
||
|
||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
#endregion
|
||
public void Dispose()
|
||
{
|
||
try
|
||
{
|
||
// 1. 【核心修复】必须取消订阅 CollectionChanged 事件,否则 VM 永远无法被释放
|
||
if (Program != null)
|
||
{
|
||
if (Program.StepCollection != null)
|
||
{
|
||
Program.StepCollection.CollectionChanged -= StepCollection_CollectionChanged;
|
||
}
|
||
if (Program.ErrorStepCollection != null)
|
||
{
|
||
Program.ErrorStepCollection.CollectionChanged -= StepCollection_CollectionChanged;
|
||
}
|
||
}
|
||
|
||
// 2. 【核心修复】必须显式退订 Prism 全局事件(AlarmEvent)
|
||
// 注意:因为订阅时使用的是匿名 Lambda,最安全稳妥的退订方式是把整个事件上的当前 VM 订阅者全部注销
|
||
_eventAggregator?.GetEvent<AlarmEvent>()?.Unsubscribe(null);
|
||
|
||
// 3. 清空临时缓存集合与 UI 绑定列表,避免悬挂指针
|
||
tmpCopyList?.Clear();
|
||
tmpCopyList = null!;
|
||
|
||
SelectedItems?.Clear();
|
||
SelectedItems = null!;
|
||
|
||
// 4. 清除选中项状态引用
|
||
SelectedStep = null;
|
||
if (_ScopedContext != null)
|
||
{
|
||
_ScopedContext.SelectedStep = null;
|
||
_ScopedContext = null!; // 断开上下文引用
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Logger.LoggerHelper.Error($"释放步骤管理组件(StepsManagerViewModel)资源失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|