子程序使用优化
This commit is contained in:
@@ -16,6 +16,7 @@ using System.Xml;
|
||||
using UIShare.GlobalVariable;
|
||||
using UIShare.ViewModelBase;
|
||||
using Prism.Events;
|
||||
using Prism.Commands;
|
||||
|
||||
namespace TestingModule.ViewModels
|
||||
{
|
||||
@@ -94,6 +95,44 @@ namespace TestingModule.ViewModels
|
||||
public ICommand DeleteStepCommand { get;set; }
|
||||
public ICommand TabSelectionChangedCommand { get;set; }
|
||||
public ICommand SelectionChangedCommand { get;set; }
|
||||
public ICommand OpenSubProgramCommand { get; set; }
|
||||
public ICommand GoBackCommand { get; set; }
|
||||
#endregion
|
||||
|
||||
#region 子程序导航
|
||||
|
||||
/// <summary>
|
||||
/// 当前显示的程序(绑定到 DataGrid 的 ItemsSource 根)。
|
||||
/// 委托到 ScopedContext.CurrentProgram,保证 ShellViewModel 也能通过 ScopedContext 访问。
|
||||
/// </summary>
|
||||
public ProgramVM CurrentProgram
|
||||
{
|
||||
get => _ScopedContext.CurrentProgram;
|
||||
set
|
||||
{
|
||||
if (_ScopedContext.CurrentProgram != value)
|
||||
{
|
||||
_ScopedContext.CurrentProgram = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string BreadcrumbPath
|
||||
{
|
||||
get => _ScopedContext.BreadcrumbPath;
|
||||
set
|
||||
{
|
||||
if (_ScopedContext.BreadcrumbPath != value)
|
||||
{
|
||||
_ScopedContext.BreadcrumbPath = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanGoBack => _ScopedContext.CanGoBack;
|
||||
|
||||
#endregion
|
||||
|
||||
public StepsManagerViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider)
|
||||
@@ -108,9 +147,31 @@ namespace TestingModule.ViewModels
|
||||
DeleteStepCommand = new DelegateCommand(DeleteStep);
|
||||
TabSelectionChangedCommand = new DelegateCommand<string>(TabSelectionChanged);
|
||||
SelectionChangedCommand = new DelegateCommand<object>(SelectionChanged);
|
||||
OpenSubProgramCommand = new DelegateCommand(OpenSubProgram);
|
||||
GoBackCommand = new DelegateCommand(GoBack);
|
||||
SubscribeStepCollections();
|
||||
Program.PropertyChanged += Program_PropertyChanged;
|
||||
Admin = _globalInfo.IsAdmin;
|
||||
|
||||
// 初始化 CurrentProgram 为根程序
|
||||
_ScopedContext.CurrentProgram = Program;
|
||||
_ScopedContext.BreadcrumbPath = "主程序";
|
||||
|
||||
// 订阅 ScopedContext 属性变化,外部(ShellViewModel)修改时转发通知给 UI
|
||||
_ScopedContext.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(ScopedContext.CurrentProgram))
|
||||
RaisePropertyChanged(nameof(CurrentProgram));
|
||||
else if (e.PropertyName == nameof(ScopedContext.BreadcrumbPath))
|
||||
RaisePropertyChanged(nameof(BreadcrumbPath));
|
||||
else if (e.PropertyName == nameof(ScopedContext.CanGoBack))
|
||||
RaisePropertyChanged(nameof(CanGoBack));
|
||||
};
|
||||
|
||||
// 订阅子程序导航事件(运行时由 StepRunning 发布)
|
||||
_eventAggregator.GetEvent<SubProgramNavigateEvent>()
|
||||
.Subscribe(OnSubProgramNavigate, ThreadOption.UIThread, false,
|
||||
payload => payload.Scope == _systemConfig.Title);
|
||||
}
|
||||
|
||||
private void SelectionChanged(object parameter)
|
||||
@@ -208,6 +269,72 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 子程序导航方法
|
||||
|
||||
/// <summary>
|
||||
/// 编辑模式:右键打开子程序
|
||||
/// </summary>
|
||||
private void OpenSubProgram()
|
||||
{
|
||||
if (SelectedStep == null || SelectedStep.StepType != "子程序" || SelectedStep.SubProgram == null)
|
||||
return;
|
||||
|
||||
// 压栈:保存当前程序
|
||||
_ScopedContext.SubProgramNavigationStack.Push(CurrentProgram);
|
||||
_ScopedContext.UpdateCanGoBack();
|
||||
// 更新面包屑
|
||||
var stepName = SelectedStep.Name ?? "子程序";
|
||||
BreadcrumbPath = $"{BreadcrumbPath} > {stepName}";
|
||||
// 切换到子程序
|
||||
CurrentProgram = SelectedStep.SubProgram;
|
||||
RaisePropertyChanged(nameof(CanGoBack));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回上一级程序
|
||||
/// </summary>
|
||||
private void GoBack()
|
||||
{
|
||||
if (_ScopedContext.SubProgramNavigationStack.Count == 0)
|
||||
return;
|
||||
|
||||
// 出栈:恢复上一级程序
|
||||
var parentProgram = _ScopedContext.SubProgramNavigationStack.Pop();
|
||||
_ScopedContext.UpdateCanGoBack();
|
||||
CurrentProgram = parentProgram;
|
||||
|
||||
// 更新面包屑:去掉最后一段
|
||||
var parts = BreadcrumbPath.Split(" > ");
|
||||
if (parts.Length > 1)
|
||||
BreadcrumbPath = string.Join(" > ", parts.Take(parts.Length - 1));
|
||||
else
|
||||
BreadcrumbPath = "主程序";
|
||||
|
||||
RaisePropertyChanged(nameof(CanGoBack));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行时:处理 StepRunning 发布的子程序导航事件
|
||||
/// </summary>
|
||||
private void OnSubProgramNavigate(SubProgramNavigatePayload payload)
|
||||
{
|
||||
if (payload.Action == NavigateAction.Enter && payload.SubProgram != null)
|
||||
{
|
||||
_ScopedContext.SubProgramNavigationStack.Push(CurrentProgram);
|
||||
_ScopedContext.UpdateCanGoBack();
|
||||
CurrentProgram = payload.SubProgram;
|
||||
var stepName = payload.StepName ?? "子程序";
|
||||
BreadcrumbPath = $"{BreadcrumbPath} > {stepName}";
|
||||
RaisePropertyChanged(nameof(CanGoBack));
|
||||
}
|
||||
else if (payload.Action == NavigateAction.Exit)
|
||||
{
|
||||
GoBack();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
/// <summary>
|
||||
@@ -304,9 +431,9 @@ namespace TestingModule.ViewModels
|
||||
Program.PropertyChanged -= Program_PropertyChanged;
|
||||
}
|
||||
|
||||
// 3. 【核心修复】必须显式退订 Prism 全局事件(AlarmEvent)
|
||||
// 注意:因为订阅时使用的是匿名 Lambda,最安全稳妥的退订方式是把整个事件上的当前 VM 订阅者全部注销
|
||||
// 3. 【核心修复】必须显式退订 Prism 全局事件
|
||||
_eventAggregator?.GetEvent<AlarmEvent>()?.Unsubscribe(null);
|
||||
_eventAggregator?.GetEvent<SubProgramNavigateEvent>()?.Unsubscribe(null);
|
||||
|
||||
// 4. 清空临时缓存集合与 UI 绑定列表,避免悬挂指针
|
||||
tmpCopyList?.Clear();
|
||||
|
||||
Reference in New Issue
Block a user