using DeviceCommand.Base; using MaterialDesignThemes.Wpf; using Prism.Mvvm; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Media; using UIShare.UIViewModel; namespace UIShare.GlobalVariable { public class ScopedContext : BindableBase { private static readonly Random _randomSeed = new Random(); #region 子程序导航栈(台架隔离) /// /// 子程序导航栈:记录从根程序进入子程序的路径。 /// 每个台架(ScopedContext 实例)各自维护一个独立的栈,互不干扰。 /// public Stack SubProgramNavigationStack { get; } = new(); private ProgramVM _currentProgram; /// /// 当前在 StepManager 中显示的程序(可能是根程序,也可能是某层子程序)。 /// UI 的 DataGrid 绑定此属性,而非直接绑定 Program。 /// public ProgramVM CurrentProgram { get => _currentProgram; set => SetProperty(ref _currentProgram, value); } private string _breadcrumbPath = "主程序"; /// /// 面包屑导航路径,如 "主程序 > 连接流程 > 初始化" /// public string BreadcrumbPath { get => _breadcrumbPath; set => SetProperty(ref _breadcrumbPath, value); } private bool _canGoBack; /// /// 是否可以返回上一级(导航栈不为空时为 true) /// public bool CanGoBack { get => _canGoBack; set => SetProperty(ref _canGoBack, value); } /// /// 清空导航栈,回到根程序界面 /// public void ResetNavigation() { SubProgramNavigationStack.Clear(); CurrentProgram = Program; BreadcrumbPath = "主程序"; CanGoBack = false; } /// /// 根据栈状态刷新 CanGoBack /// public void UpdateCanGoBack() => CanGoBack = SubProgramNavigationStack.Count > 0; /// /// 当前导航深度(0 = 根程序,1 = 第一层子程序,以此类推) /// public int NavigationDepth => SubProgramNavigationStack.Count; #endregion public ProgramVM Program { get; set; } = new(); public String SelectedStepList { get; set; } = "主程序"; public string CurrentFilePath { get; set; } public bool? IsStop { get; set; } public bool SingleStep { get; set; } public string RunState { get; set; } = "运行"; public TimeSpan RunningTime { get; set; } = TimeSpan.Zero; public Stopwatch SW { get; set; } = new(); public bool IsTerminate { get; set; } = false; public ObservableCollection Assemblies { get; set; } = new(); public PackIconKind RunIcon { get; set; } = PackIconKind.Play; public StepVM SelectedStep { get; set; } public ParameterVM SelectedParameter { get; set; } public List DeviceList { get; set; } = new(); /// /// 日志缓冲队列:后台线程(ScopeLogDispatcher)直接入队, /// UI 线程(DispatcherTimer)定时出队并刷新到 ObservableCollection。 /// 不走 Progress<T> / SynchronizationContext,避免 Post 淹没 UI 消息队列。 /// public ConcurrentQueue<(string Message, Brush Color, int Depth)> LogBuffer { get; } = new(); // 【新增测试属性】:每个实例被 new 出来时独一无二的随机身份 // 证 ID public int DebugRandomId { get; private set; } public ScopedContext() { lock (_randomSeed) { // 每次诞生一个新上下文,就在 10000 到 99999 之间随机摇一个数 DebugRandomId = _randomSeed.Next(10000, 100000); } } } }