添加项目文件。
This commit is contained in:
590
TestingModule/ViewModels/CommandTreeViewModel.cs
Normal file
590
TestingModule/ViewModels/CommandTreeViewModel.cs
Normal file
@@ -0,0 +1,590 @@
|
||||
using UIShare.UIViewModel;
|
||||
using UIShare.GlobalVariable;
|
||||
using Common.Attributes;
|
||||
using Logger;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Xml;
|
||||
using Model;
|
||||
using static UIShare.UIViewModel.ParameterModel;
|
||||
using UIShare.ViewModelBase;
|
||||
using NLog;
|
||||
|
||||
namespace TestingModule.ViewModels
|
||||
{
|
||||
public class CommandTreeViewModel:NavigateViewModelBase
|
||||
{
|
||||
#region 属性
|
||||
private string _SearchText;
|
||||
|
||||
public string SearchText
|
||||
{
|
||||
get => _SearchText;
|
||||
set => SetProperty(ref _SearchText, value);
|
||||
}
|
||||
private ObservableCollection<InstructionNode> _instructionTree = new();
|
||||
public ObservableCollection<InstructionNode> InstructionTree
|
||||
{
|
||||
get => _instructionTree;
|
||||
set => SetProperty(ref _instructionTree, value);
|
||||
}
|
||||
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _ScopedContext.Program;
|
||||
set
|
||||
{
|
||||
if (_ScopedContext.Program != value)
|
||||
{
|
||||
_ScopedContext.Program = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<Assembly> Assemblies
|
||||
{
|
||||
get => _ScopedContext.Assemblies;
|
||||
set
|
||||
{
|
||||
if (_ScopedContext.Assemblies != value)
|
||||
{
|
||||
_ScopedContext.Assemblies = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<SubProgramItem> _subPrograms = new();
|
||||
public ObservableCollection<SubProgramItem> SubPrograms
|
||||
{
|
||||
get => _subPrograms;
|
||||
set => SetProperty(ref _subPrograms, value);
|
||||
}
|
||||
|
||||
private Dictionary<object, InstructionNode> _treeNodeMap = new();
|
||||
public Dictionary<object, InstructionNode> TreeNodeMap
|
||||
{
|
||||
get => _treeNodeMap;
|
||||
set => SetProperty(ref _treeNodeMap, value);
|
||||
}
|
||||
|
||||
private Dictionary<string, XmlDocument> _xmlDocumentCache = new();
|
||||
|
||||
public Dictionary<string, XmlDocument> XmlDocumentCache
|
||||
{
|
||||
get => _xmlDocumentCache;
|
||||
set => SetProperty(ref _xmlDocumentCache, value);
|
||||
}
|
||||
#endregion
|
||||
public ICommand LoadedCommand { get; set; }
|
||||
public ICommand SearchEnterCommand { get; set; }
|
||||
public ICommand TreeDoubleClickCommand { get; set; }
|
||||
public ICommand ReloadCommand { get; set; }
|
||||
private ScopedContext _ScopedContext { get; set; }
|
||||
private readonly SystemConfig _systemConfig;
|
||||
private readonly GlobalInfo _globalInfo;
|
||||
|
||||
public CommandTreeViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider)
|
||||
{
|
||||
_ScopedContext = scopedContext;
|
||||
_systemConfig = systemConfig;
|
||||
_globalInfo = globalInfo;
|
||||
LoadedCommand = new DelegateCommand(Loaded);
|
||||
SearchEnterCommand = new DelegateCommand(Search);
|
||||
TreeDoubleClickCommand = new DelegateCommand<object>(TreeDoubleClick);
|
||||
ReloadCommand = new DelegateCommand(Reload);
|
||||
}
|
||||
|
||||
|
||||
#region 委托命令
|
||||
private void Reload()
|
||||
{
|
||||
LoadAllAssemblies();
|
||||
LoadSubPrograms();
|
||||
LoadInstructionsToTreeView();
|
||||
}
|
||||
private void TreeDoubleClick(object obj)
|
||||
{
|
||||
if (!_globalInfo.IsAdmin) return;
|
||||
if(obj is InstructionNode Node)
|
||||
{
|
||||
if(Node.Children.Count == 0)
|
||||
{
|
||||
int index = _ScopedContext.SelectedStep?.Index >= 0 ? _ScopedContext.SelectedStep.Index : -1;
|
||||
if (Node.Tag is MethodInfo method)
|
||||
{
|
||||
AddMethodToProgram(method, index);
|
||||
}
|
||||
else if(Node.Tag is string tag)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case "循环开始":
|
||||
AddLoopStartStep(index);
|
||||
break;
|
||||
case "循环结束":
|
||||
AddLoopEndStep(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(Node.Tag is SubProgramItem subProgram)
|
||||
{
|
||||
AddSubProgramToProgram(subProgram, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Search()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void Loaded()
|
||||
{
|
||||
LoadAllAssemblies();
|
||||
LoadSubPrograms();
|
||||
LoadInstructionsToTreeView();
|
||||
}
|
||||
#endregion
|
||||
#region 加载指令
|
||||
/// <summary>
|
||||
/// 加载指定目录下的所有DLL
|
||||
/// </summary>
|
||||
private void LoadAllAssemblies()
|
||||
{
|
||||
Assemblies.Clear();
|
||||
|
||||
foreach (var dllPath in Directory.GetFiles(_systemConfig.DLLFilePath, "*.dll"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.LoadFile(dllPath);
|
||||
Assemblies.Add(assembly);
|
||||
|
||||
// 加载对应的XML注释文件 (项目没有用到)
|
||||
//string xmlPath = Path.ChangeExtension(dllPath, ".xml");
|
||||
//if (File.Exists(xmlPath))
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// XmlDocument xmlDoc = new XmlDocument();
|
||||
// xmlDoc.Load(xmlPath);
|
||||
// _xmlDocumentCache[assembly.FullName!] = xmlDoc;
|
||||
// }
|
||||
// catch (Exception xmlEx)
|
||||
// {
|
||||
// LoggerHelper.WarnWithNotify($"加载XML注释失败: {Path.GetFileName(xmlPath)} - {xmlEx.Message}");
|
||||
// }
|
||||
//}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"无法加载程序集 {Path.GetFileName(dllPath)}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 子程序加载方法
|
||||
private void LoadSubPrograms()
|
||||
{
|
||||
SubPrograms.Clear();
|
||||
|
||||
if (!Directory.Exists(_systemConfig.SubProgramFilePath))
|
||||
{
|
||||
Directory.CreateDirectory(_systemConfig.SubProgramFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var filePath in Directory.GetFiles(_systemConfig.SubProgramFilePath, "*.adp"))
|
||||
{
|
||||
try
|
||||
{
|
||||
SubPrograms.Add(new SubProgramItem
|
||||
{
|
||||
Name = Path.GetFileNameWithoutExtension(filePath),
|
||||
FilePath = filePath
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"加载子程序错误: {filePath} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 加载指令集到TreeView
|
||||
/// </summary>
|
||||
private void LoadInstructionsToTreeView()
|
||||
{
|
||||
InstructionTree.Clear();
|
||||
var controlRootNode = new InstructionNode
|
||||
{
|
||||
Name = "系统指令",
|
||||
Tag = "ControlRoot"
|
||||
};
|
||||
InstructionTree.Add(controlRootNode);
|
||||
|
||||
// 循环开始
|
||||
controlRootNode.Children.Add(new InstructionNode
|
||||
{
|
||||
Name = "循环开始",
|
||||
Tag = "循环开始"
|
||||
});
|
||||
|
||||
// 循环结束
|
||||
controlRootNode.Children.Add(new InstructionNode
|
||||
{
|
||||
Name = "循环结束",
|
||||
Tag = "循环结束"
|
||||
});
|
||||
|
||||
// ----------------------
|
||||
// 子程序 根节点
|
||||
// ----------------------
|
||||
var subProgramRoot = new InstructionNode
|
||||
{
|
||||
Name = "子程序",
|
||||
Tag = "SubProgramRoot"
|
||||
};
|
||||
InstructionTree.Add(subProgramRoot);
|
||||
|
||||
foreach (var subProgram in SubPrograms)
|
||||
{
|
||||
subProgramRoot.Children.Add(new InstructionNode
|
||||
{
|
||||
Name = subProgram.Name,
|
||||
Tag = subProgram,
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// 动态 DLL 指令
|
||||
// ----------------------
|
||||
foreach (var assembly in Assemblies)
|
||||
{
|
||||
List<Type> validTypes = new List<Type>();
|
||||
try
|
||||
{
|
||||
var types = assembly.GetTypes().Where(t =>
|
||||
t.IsPublic &&
|
||||
!t.IsNested &&
|
||||
|
||||
(t.IsClass || t.IsValueType) &&
|
||||
(!t.IsAbstract || t.IsSealed) &&
|
||||
t.GetCustomAttribute<ADPCommandAttribute>() != null);
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
if (type.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false)
|
||||
continue;
|
||||
|
||||
var allMethods = new HashSet<MethodInfo>();
|
||||
GetPublicMethods(type, allMethods);
|
||||
|
||||
if (allMethods.Count > 0)
|
||||
validTypes.Add(type);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"加载类型错误: {assembly.FullName} - {ex.Message}");
|
||||
}
|
||||
|
||||
if (validTypes.Count > 0)
|
||||
{
|
||||
var assemblyNode = new InstructionNode
|
||||
{
|
||||
Name = assembly.GetName().Name,
|
||||
Tag = assembly
|
||||
};
|
||||
InstructionTree.Add(assemblyNode);
|
||||
TreeNodeMap[assembly] = assemblyNode;
|
||||
|
||||
foreach (var type in validTypes)
|
||||
{
|
||||
//拦截没有在设备列表中的设备类型
|
||||
//if (SystemConfig.Instance.DeviceList.Where(x=>x.Remark==type.Name).ToList().Count==0 && type.FullName.Contains("DeviceCommand.Device"))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
var typeNode = new InstructionNode
|
||||
{
|
||||
Name = type.Name,
|
||||
Tag = type,
|
||||
};
|
||||
assemblyNode.Children.Add(typeNode);
|
||||
TreeNodeMap[type] = typeNode;
|
||||
|
||||
var allMethods = new HashSet<MethodInfo>();
|
||||
GetPublicMethods(type, allMethods);
|
||||
|
||||
foreach (var method in allMethods)
|
||||
{
|
||||
if (method.IsSpecialName) continue;
|
||||
if (method.DeclaringType == typeof(object)) continue;
|
||||
|
||||
string[] ignoreMethods = { "GetType", "ToString", "Equals", "GetHashCode" };
|
||||
if (ignoreMethods.Contains(method.Name)) continue;
|
||||
|
||||
if (method.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false)
|
||||
continue;
|
||||
if (type.IsAbstract && type.IsSealed && !method.IsStatic) continue;
|
||||
|
||||
var parameters = method.GetParameters();
|
||||
var paramText = string.Join(", ", parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));
|
||||
|
||||
var methodNode = new InstructionNode
|
||||
{
|
||||
Name = $"{method.Name}({paramText})",
|
||||
Tag = method,
|
||||
};
|
||||
|
||||
typeNode.Children.Add(methodNode);
|
||||
TreeNodeMap[method] = methodNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 辅助方法
|
||||
/// <summary>
|
||||
/// 递归获取类型的所有公共方法(包括继承的方法),但跳过被重写的方法
|
||||
/// </summary>
|
||||
/// <param name="type">要处理的目标类型</param>
|
||||
/// <param name="methods">存储方法的集合</param>
|
||||
private void GetPublicMethods(Type type, HashSet<MethodInfo> methods)
|
||||
{
|
||||
// 获取当前类型的所有公共方法(包括继承的)
|
||||
var allMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
|
||||
.Where(m => !m.IsSpecialName &&
|
||||
m.DeclaringType != typeof(object))
|
||||
.ToList();
|
||||
|
||||
// 按方法签名分组
|
||||
var groupedMethods = allMethods
|
||||
.GroupBy(m => new { m.Name, Parameters = string.Join(",", m.GetParameters().Select(p => p.ParameterType.FullName)) });
|
||||
|
||||
foreach (var group in groupedMethods)
|
||||
{
|
||||
// 从组中选择声明类型最接近当前类型(即继承层次最深)的方法
|
||||
MethodInfo? selectedMethod = null;
|
||||
int minDepth = int.MaxValue;
|
||||
|
||||
foreach (var method in group)
|
||||
{
|
||||
// 计算声明类型的深度
|
||||
int depth = 0;
|
||||
Type? current = type;
|
||||
Type declaringType = method.DeclaringType!;
|
||||
|
||||
while (current != null && current != declaringType)
|
||||
{
|
||||
depth++;
|
||||
current = current.BaseType;
|
||||
}
|
||||
|
||||
// 如果找到声明类型且在继承链上
|
||||
if (current == declaringType)
|
||||
{
|
||||
if (selectedMethod == null || depth < minDepth)
|
||||
{
|
||||
selectedMethod = method;
|
||||
minDepth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedMethod != null)
|
||||
{
|
||||
methods.Add(selectedMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region 指令添加
|
||||
|
||||
private void AddMethodToProgram(MethodInfo method, int insertIndex = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = method.Name,
|
||||
StepType = "方法",
|
||||
Method = new MethodModel
|
||||
{
|
||||
FullName = method.DeclaringType?.FullName,
|
||||
Name = method.Name
|
||||
}
|
||||
};
|
||||
|
||||
// 添加输入参数
|
||||
foreach (var param in method.GetParameters())
|
||||
{
|
||||
newStep.Method.Parameters.Add(new ParameterModel
|
||||
{
|
||||
Name = param.Name!,
|
||||
Type = param.ParameterType,
|
||||
Category = ParameterCategory.Input
|
||||
});
|
||||
}
|
||||
|
||||
// 添加输出参数(返回值)
|
||||
Type returnType = method.ReturnType;
|
||||
if (returnType == typeof(Task))
|
||||
{
|
||||
// 不添加输出参数(无返回值)
|
||||
}
|
||||
else if (returnType.IsGenericType &&
|
||||
returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
{
|
||||
// 提取实际返回类型(如 Task<bool> -> bool)
|
||||
Type actualType = returnType.GetGenericArguments()[0];
|
||||
newStep.Method.Parameters.Add(new ParameterModel
|
||||
{
|
||||
Name = "Result",
|
||||
Type = actualType, // 使用实际类型
|
||||
Category = ParameterCategory.Output
|
||||
});
|
||||
}
|
||||
else if (returnType != typeof(void))
|
||||
{
|
||||
// 同步方法正常添加
|
||||
newStep.Method.Parameters.Add(new ParameterModel
|
||||
{
|
||||
Name = "Result",
|
||||
Type = returnType,
|
||||
Category = ParameterCategory.Output
|
||||
});
|
||||
}
|
||||
|
||||
// 添加到程序
|
||||
if(_ScopedContext.SelectedStepList == "主程序")
|
||||
{
|
||||
if(insertIndex >= 0 && insertIndex <= Program.StepCollection.Count) Program.StepCollection.Insert(insertIndex, newStep);
|
||||
else Program.StepCollection.Add(newStep); }
|
||||
else
|
||||
{
|
||||
if (insertIndex >= 0 && insertIndex <= Program.ErrorStepCollection.Count) Program.ErrorStepCollection.Insert(insertIndex, newStep);
|
||||
else Program.ErrorStepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"添加方法失败: {method.Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSubProgramToProgram(SubProgramItem subProgram, int insertIndex = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = subProgram.Name,
|
||||
StepType = "子程序"
|
||||
};
|
||||
var jsonstr = File.ReadAllText($"{subProgram.FilePath}");
|
||||
var tmp = JsonConvert.DeserializeObject<ProgramModel>(jsonstr);
|
||||
if (tmp != null)
|
||||
{
|
||||
newStep.SubProgram = tmp;
|
||||
}
|
||||
// 添加到程序
|
||||
if (_ScopedContext.SelectedStepList == "主程序")
|
||||
{
|
||||
if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count) Program.StepCollection.Insert(insertIndex, newStep);
|
||||
else Program.StepCollection.Add(newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (insertIndex >= 0 && insertIndex <= Program.ErrorStepCollection.Count) Program.ErrorStepCollection.Insert(insertIndex, newStep);
|
||||
else Program.ErrorStepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"添加子程序失败: {subProgram.Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLoopStartStep(int insertIndex = -1)
|
||||
{
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = "循环开始",
|
||||
StepType = "循环开始",
|
||||
LoopCount = 1,
|
||||
Method = new() { Parameters = [new() { Name = "循环次数", Type = typeof(int), Category = ParameterCategory.Input }] }
|
||||
};
|
||||
|
||||
// 添加到程序
|
||||
if (_ScopedContext.SelectedStepList == "主程序")
|
||||
{
|
||||
if (insertIndex >= 0) Program.StepCollection.Insert(insertIndex, newStep);
|
||||
else Program.StepCollection.Add(newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (insertIndex >= 0) Program.ErrorStepCollection.Insert(insertIndex, newStep);
|
||||
else Program.ErrorStepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLoopEndStep(int insertIndex = -1)
|
||||
{
|
||||
// 查找最近的未匹配循环开始
|
||||
StepModel? lastUnmatchedLoopStart = null;
|
||||
for (int i = Program.StepCollection.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (Program.StepCollection[i].StepType == "循环开始")
|
||||
{
|
||||
bool isMatched = Program.StepCollection.Any(s => s.StepType == "循环结束" && s.LoopStartStepId == Program.StepCollection[i].ID);
|
||||
|
||||
if (!isMatched)
|
||||
{
|
||||
lastUnmatchedLoopStart = Program.StepCollection[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = "循环结束",
|
||||
StepType = "循环结束",
|
||||
LoopStartStepId = lastUnmatchedLoopStart?.ID
|
||||
};
|
||||
|
||||
// 添加到程序
|
||||
if (_ScopedContext.SelectedStepList == "主程序")
|
||||
{
|
||||
if (insertIndex >= 0) Program.StepCollection.Insert(insertIndex, newStep);
|
||||
else Program.StepCollection.Add(newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (insertIndex >= 0) Program.ErrorStepCollection.Insert(insertIndex, newStep);
|
||||
else Program.ErrorStepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
135
TestingModule/ViewModels/Dialogs/ParameterSettingViewModel.cs
Normal file
135
TestingModule/ViewModels/Dialogs/ParameterSettingViewModel.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using UIShare.UIViewModel;
|
||||
using UIShare.PubEvent;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using UIShare.GlobalVariable;
|
||||
using static UIShare.UIViewModel.ParameterModel;
|
||||
using UIShare.ViewModelBase;
|
||||
using Prism.Ioc;
|
||||
using Prism.Navigation.Regions;
|
||||
|
||||
namespace TestingModule.ViewModels.Dialogs
|
||||
{
|
||||
public class ParameterSettingViewModel : DialogViewModelBase
|
||||
{
|
||||
#region 属性
|
||||
private string _title = "参数设置界面";
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set => SetProperty(ref _title, value);
|
||||
}
|
||||
private Array _EnumValues;
|
||||
public Array EnumValues
|
||||
{
|
||||
get => _EnumValues;
|
||||
set => SetProperty(ref _EnumValues, value);
|
||||
}
|
||||
private ObservableCollection<Type> _types =
|
||||
[
|
||||
typeof(string), typeof(bool),
|
||||
typeof(short), typeof(int), typeof(long), typeof(float), typeof(double),
|
||||
typeof(byte[]), typeof(short[]), typeof(ushort[]), typeof(int[]), typeof(long[]), typeof(float[]), typeof(double[]),
|
||||
typeof(object)
|
||||
];
|
||||
public ObservableCollection<Type> Types
|
||||
{
|
||||
get => _types;
|
||||
set => SetProperty(ref _types, value);
|
||||
}
|
||||
|
||||
private ObservableCollection<string> _categories = new ObservableCollection<string>(
|
||||
Enum.GetNames(typeof(ParameterCategory))
|
||||
);
|
||||
public ObservableCollection<string> Categories
|
||||
{
|
||||
get => _categories;
|
||||
set => SetProperty(ref _categories, value);
|
||||
}
|
||||
private string _Mode;
|
||||
public string Mode
|
||||
{
|
||||
get => _Mode;
|
||||
set => SetProperty(ref _Mode, value);
|
||||
}
|
||||
|
||||
private ProgramModel _program;
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _program;
|
||||
set => SetProperty(ref _program, value);
|
||||
}
|
||||
private ParameterModel _Parameter;
|
||||
public ParameterModel Parameter
|
||||
{
|
||||
get => _Parameter;
|
||||
set => SetProperty(ref _Parameter, value);
|
||||
}
|
||||
#endregion
|
||||
public DialogCloseListener RequestClose{get;set;}
|
||||
private ScopedContext _ScopedContext;
|
||||
public ICommand CancelCommand { get; set; }
|
||||
public ICommand SaveCommand { get; set; }
|
||||
public ParameterSettingViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
CancelCommand = new DelegateCommand(Cancel);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
if (Mode == "ADD")
|
||||
{
|
||||
Program.Parameters.Add(Parameter);
|
||||
_ScopedContext.SelectedParameter = Parameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = Program.Parameters
|
||||
.Select((x, i) => new { x, i })
|
||||
.FirstOrDefault(p => p.x.ID == _ScopedContext.SelectedParameter.ID)?.i;
|
||||
|
||||
if (index.HasValue)
|
||||
{
|
||||
Program.Parameters[index.Value] = Parameter;
|
||||
}
|
||||
}
|
||||
|
||||
RequestClose.Invoke(ButtonResult.OK);
|
||||
}
|
||||
|
||||
private void Cancel()
|
||||
{
|
||||
RequestClose.Invoke(ButtonResult.No);
|
||||
}
|
||||
#region Prism Dialog 规范
|
||||
|
||||
public override void OnDialogClosed()
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
}
|
||||
|
||||
public override void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
if (parameters.ContainsKey("ScopedContext"))
|
||||
_ScopedContext = parameters.GetValue<ScopedContext>("ScopedContext");
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
Program =_ScopedContext.Program;
|
||||
Mode = parameters.GetValue<string>("Mode");
|
||||
if (Mode == "ADD")
|
||||
{
|
||||
Parameter = new();
|
||||
}
|
||||
else
|
||||
{
|
||||
Parameter = new ParameterModel(_ScopedContext.SelectedParameter);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
58
TestingModule/ViewModels/LogAreaViewModel.cs
Normal file
58
TestingModule/ViewModels/LogAreaViewModel.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using UIShare.GlobalVariable;
|
||||
using Logger;
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using UIShare.ViewModelBase;
|
||||
|
||||
namespace TestingModule.ViewModels
|
||||
{
|
||||
public class LogAreaViewModel : NavigateViewModelBase
|
||||
{
|
||||
// 日志集合
|
||||
private ObservableCollection<LogItem> _logs = new();
|
||||
|
||||
|
||||
public ObservableCollection<LogItem> Logs
|
||||
{
|
||||
get => _logs;
|
||||
set => SetProperty(ref _logs, value);
|
||||
}
|
||||
public ICommand ClearLogCommand { get; set; }
|
||||
|
||||
public LogAreaViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
ClearLogCommand = new DelegateCommand(ClearLog);
|
||||
LoggerHelper.Progress = new System.Progress<(string message, string color, int depth)>(
|
||||
log =>
|
||||
{
|
||||
var brush = (Brush)new BrushConverter().ConvertFromString(log.color);
|
||||
Logs.Add(new LogItem(log.message, brush, log.depth));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void ClearLog()
|
||||
{
|
||||
Logs.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 日志条目类
|
||||
public class LogItem
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public Brush Color { get; set; } = Brushes.Black;
|
||||
public int Depth { get; set; }
|
||||
public LogItem(string message, Brush color, int depth = 0)
|
||||
{
|
||||
Message = new string(' ', depth * 20) + message;
|
||||
Color = color;
|
||||
Depth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
165
TestingModule/ViewModels/ParametersManagerViewModel.cs
Normal file
165
TestingModule/ViewModels/ParametersManagerViewModel.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using UIShare.UIViewModel;
|
||||
using UIShare.GlobalVariable;
|
||||
using UIShare.PubEvent;
|
||||
using Logger;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
using System.Xml;
|
||||
using UIShare.ViewModelBase;
|
||||
using Prism.Events;
|
||||
|
||||
namespace TestingModule.ViewModels
|
||||
{
|
||||
public class ParametersManagerViewModel:NavigateViewModelBase
|
||||
{
|
||||
#region 属性
|
||||
//private ObservableCollection<DeviceConfigModel> _DeviceList;
|
||||
|
||||
//public ObservableCollection<DeviceConfigModel> DeviceList
|
||||
//{
|
||||
// get { return _DeviceList; }
|
||||
// set { SetProperty(ref _DeviceList,value); }
|
||||
//}
|
||||
private ObservableCollection<DeviceInfoModel> _DeviceInfoModel;
|
||||
|
||||
public ObservableCollection<DeviceInfoModel> DeviceInfoModel
|
||||
{
|
||||
get { return _DeviceInfoModel; }
|
||||
set { SetProperty(ref _DeviceInfoModel, value); }
|
||||
}
|
||||
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _ScopedContext.Program;
|
||||
set
|
||||
{
|
||||
if (_ScopedContext.Program != value)
|
||||
{
|
||||
_ScopedContext.Program = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
private ParameterModel _SelectedParameter;
|
||||
public ParameterModel SelectedParameter
|
||||
{
|
||||
get => _SelectedParameter;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _SelectedParameter, value))
|
||||
{
|
||||
_ScopedContext.SelectedParameter = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private DeviceInfoModel _SelectedDevice;
|
||||
|
||||
|
||||
|
||||
public DeviceInfoModel SelectedDevice
|
||||
{
|
||||
get { return _SelectedDevice; }
|
||||
set { SetProperty(ref _SelectedDevice, value); }
|
||||
}
|
||||
#endregion
|
||||
private ScopedContext _ScopedContext { get; set; }
|
||||
private readonly SystemConfig _systemConfig;
|
||||
private readonly GlobalInfo _globalInfo;
|
||||
#region 命令
|
||||
public ICommand ParameterAddCommand { get; set; }
|
||||
public ICommand ParameterEditCommand { get; set; }
|
||||
public ICommand ParameterDeleteCommand { get; set; }
|
||||
public ICommand DeviceEditCommand { get; set; }
|
||||
public ICommand ReconnnectCommand { get; set; }
|
||||
public ICommand CloseCommand { get; set; }
|
||||
#endregion
|
||||
|
||||
public ParametersManagerViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider)
|
||||
{
|
||||
_ScopedContext = scopedContext;
|
||||
_systemConfig = systemConfig;
|
||||
_globalInfo = globalInfo;
|
||||
Program = _ScopedContext.Program;
|
||||
ParameterAddCommand = new DelegateCommand(ParameterAdd);
|
||||
ParameterEditCommand = new DelegateCommand(ParameterEdit);
|
||||
ParameterDeleteCommand = new DelegateCommand(ParameterDelete);
|
||||
DeviceEditCommand = new DelegateCommand(DeviceEdit);
|
||||
}
|
||||
|
||||
#region 委托命令
|
||||
|
||||
private void DeviceEdit()
|
||||
{
|
||||
if (!_globalInfo.IsAdmin) return;
|
||||
if (SelectedDevice==null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var type = SelectedDevice.DeviceType.Split('.').Last();
|
||||
if(type=="E36233A"|| type == "IT6724CReverse")
|
||||
{
|
||||
_dialogService.Show("Backfeed");
|
||||
}
|
||||
else
|
||||
{
|
||||
_dialogService.Show(type);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParameterDelete()
|
||||
{
|
||||
if (!_globalInfo.IsAdmin) return;
|
||||
Program.Parameters.Remove(SelectedParameter);
|
||||
}
|
||||
|
||||
private void ParameterEdit()
|
||||
{
|
||||
if (!_globalInfo.IsAdmin) return;
|
||||
var param = new DialogParameters
|
||||
{
|
||||
{ "Mode",SelectedParameter==null?"ADD":"Edit" },
|
||||
{ "ScopedContext",_ScopedContext }
|
||||
};
|
||||
_dialogService.ShowDialog("ParameterSetting", param, (r) =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void ParameterAdd()
|
||||
{
|
||||
if (!_globalInfo.IsAdmin) return;
|
||||
var param = new DialogParameters
|
||||
{
|
||||
{ "Mode", "ADD" },
|
||||
{ "ScopedContext",_ScopedContext }
|
||||
};
|
||||
_dialogService.ShowDialog("ParameterSetting", param, (r) =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
201
TestingModule/ViewModels/SingleStepEditViewModel.cs
Normal file
201
TestingModule/ViewModels/SingleStepEditViewModel.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using UIShare.UIViewModel;
|
||||
using UIShare.PubEvent;
|
||||
using Logger;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
using SqlSugar.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using UIShare.ViewModelBase;
|
||||
using Prism.Dialogs;
|
||||
using Prism.Events;
|
||||
using UIShare.GlobalVariable;
|
||||
|
||||
namespace TestingModule.ViewModels
|
||||
{
|
||||
public class SingleStepEditViewModel:NavigateViewModelBase
|
||||
{
|
||||
#region 属性
|
||||
private Guid _ID;
|
||||
public Guid ID
|
||||
{
|
||||
get => _ID;
|
||||
set => SetProperty(ref _ID, value);
|
||||
}
|
||||
private StepModel _SelectedStep;
|
||||
public StepModel SelectedStep
|
||||
{
|
||||
get => _SelectedStep;
|
||||
set => SetProperty(ref _SelectedStep, value);
|
||||
}
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _ScopedContext.Program;
|
||||
set
|
||||
{
|
||||
if (_ScopedContext.Program != value)
|
||||
{
|
||||
_ScopedContext.Program = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
private ScopedContext _ScopedContext;
|
||||
#region 命令
|
||||
public ICommand CancelEditCommand { get; set; }
|
||||
public ICommand SaveStepCommand { get; set; }
|
||||
#endregion
|
||||
public SingleStepEditViewModel(IContainerProvider containerProvider, ScopedContext scopedContext) : base(containerProvider)
|
||||
{
|
||||
_ScopedContext = scopedContext;
|
||||
_eventAggregator.GetEvent<EditSetpEvent>().Subscribe(EditSingleStep);
|
||||
CancelEditCommand = new DelegateCommand(CancelEdit);
|
||||
SaveStepCommand = new DelegateCommand(SaveStep);
|
||||
_eventAggregator.GetEvent<DeletedStepEvent>().Subscribe(DisposeSelectedStep);
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Subscribe(ParamsChanged);
|
||||
}
|
||||
|
||||
#region 委托命令
|
||||
private void ParamsChanged()
|
||||
{
|
||||
CancelEdit();
|
||||
}
|
||||
|
||||
private void DisposeSelectedStep(Guid id)
|
||||
{
|
||||
if (SelectedStep == null) return;
|
||||
if(id== SelectedStep.ID)
|
||||
SelectedStep = null;
|
||||
}
|
||||
|
||||
private void CancelEdit()
|
||||
{
|
||||
SelectedStep = null;
|
||||
}
|
||||
|
||||
private void SaveStep()
|
||||
{
|
||||
if (SelectedStep == null || (SelectedStep.Method == null && SelectedStep.SubProgram == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var steps = _ScopedContext.SelectedStepList=="主程序"?_ScopedContext.Program.StepCollection: _ScopedContext.Program.ErrorStepCollection;
|
||||
int index = steps.ToList().FindIndex(x => x.ID == ID);
|
||||
if (index >= 0)
|
||||
{
|
||||
steps[index] = SelectedStep;
|
||||
if (steps[index].Method != null)
|
||||
{
|
||||
if (steps[index].StepType == "循环开始")
|
||||
{
|
||||
try
|
||||
{
|
||||
steps[index].LoopCount = Convert.ToInt32(SelectedStep.Method!.Parameters[0].Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("循环指令参数设置错误:类型转换失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //设置步骤参数
|
||||
(steps[index].OKGotoStepID, steps[index].NGGotoStepID) = GetOKNGGotoStepID(SelectedStep.GotoSettingString);
|
||||
for (int i = 0; i < steps[index].Method.Parameters.Count; i++)
|
||||
{
|
||||
var editedParam = SelectedStep.Method!.Parameters[i];
|
||||
var originalParam = steps[index].Method.Parameters[i];
|
||||
if (editedParam.IsUseVar)
|
||||
{
|
||||
originalParam.VariableName = editedParam.VariableName;
|
||||
originalParam.VariableID = _ScopedContext.Program.Parameters.FirstOrDefault(x => x.Name == editedParam.VariableName)!.ID;
|
||||
}
|
||||
originalParam.Value = editedParam.Value;
|
||||
originalParam.IsUseVar = editedParam.IsUseVar;
|
||||
originalParam.LowerLimit = editedParam.LowerLimit;
|
||||
originalParam.UpperLimit = editedParam.UpperLimit;
|
||||
}
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "Title", "提示" },
|
||||
{ "Message", "保存成功!" },
|
||||
{ "Icon", "info" },
|
||||
{ "ShowOk", true }
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox", parameters);
|
||||
}
|
||||
}
|
||||
else if (steps[index].SubProgram != null)
|
||||
{
|
||||
if (SelectedStep.SubProgram.Parameters.Where(x => x.VariableName == null && x.IsUseVar == true).FirstOrDefault() != null)
|
||||
{
|
||||
var parameters1 = new DialogParameters
|
||||
{
|
||||
{ "Title", "警告" },
|
||||
{ "Message", "选中变量不得为空!" },
|
||||
{ "Icon", "warn" },
|
||||
{ "ShowOk", true },
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox",parameters1);
|
||||
return;
|
||||
}
|
||||
(steps[index].OKGotoStepID, steps[index].NGGotoStepID) = GetOKNGGotoStepID(SelectedStep.GotoSettingString);
|
||||
for (int i = 0; i < steps[index].SubProgram.Parameters.Count; i++)
|
||||
{
|
||||
var editedParam = SelectedStep.SubProgram!.Parameters[i];
|
||||
var originalParam = steps[index].SubProgram.Parameters[i];
|
||||
if (editedParam.IsUseVar)
|
||||
{
|
||||
originalParam.VariableName = editedParam.VariableName;
|
||||
originalParam.VariableID = _ScopedContext.Program.Parameters.FirstOrDefault(x => x.Name == editedParam.VariableName)!.ID;
|
||||
}
|
||||
originalParam.Value = editedParam.Value;
|
||||
originalParam.IsUseVar = editedParam.IsUseVar;
|
||||
originalParam.LowerLimit = editedParam.LowerLimit;
|
||||
originalParam.UpperLimit = editedParam.UpperLimit;
|
||||
}
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "Title", "提示" },
|
||||
{ "Message", "保存成功!" },
|
||||
{ "Icon", "info" },
|
||||
{ "ShowOk", true }
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox", parameters);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private (Guid,Guid) GetOKNGGotoStepID(string GotoSettingString)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(GotoSettingString))
|
||||
return (Guid.Empty, Guid.Empty);
|
||||
|
||||
var match = Regex.Match(GotoSettingString, @"^(\d+)\s*/\s*(\d+)$");
|
||||
if (match.Success)
|
||||
{
|
||||
int ok = int.Parse(match.Groups[1].Value);
|
||||
int ng = int.Parse(match.Groups[2].Value);
|
||||
|
||||
Guid okGuid = _ScopedContext.Program.StepCollection.ElementAtOrDefault(ok-1)?.ID ?? Guid.Empty;
|
||||
Guid ngGuid = _ScopedContext.Program.StepCollection.ElementAtOrDefault(ng-1)?.ID ?? Guid.Empty;
|
||||
|
||||
return (okGuid, ngGuid);
|
||||
}
|
||||
return (Guid.Empty, Guid.Empty);
|
||||
}
|
||||
private void EditSingleStep()
|
||||
{
|
||||
if (_ScopedContext.SelectedStep == null) return;
|
||||
ID = _ScopedContext.SelectedStep.ID;
|
||||
SelectedStep = new StepModel(_ScopedContext.SelectedStep);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
237
TestingModule/ViewModels/StepsManagerViewModel.cs
Normal file
237
TestingModule/ViewModels/StepsManagerViewModel.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
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
|
||||
{
|
||||
#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<StepModel> _SelectedItems;
|
||||
public List<StepModel> SelectedItems
|
||||
{
|
||||
get { return _SelectedItems; }
|
||||
set { SetProperty(ref _SelectedItems, value); }
|
||||
}
|
||||
private StepModel _SelectedStep;
|
||||
public StepModel SelectedStep
|
||||
{
|
||||
get => _SelectedStep;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _SelectedStep, value))
|
||||
{
|
||||
_ScopedContext.SelectedStep = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public ProgramModel 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<StepModel> tmpCopyList = new List<StepModel>();
|
||||
|
||||
|
||||
#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<StepModel>().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 StepModel(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 StepModel(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<StepModel>;
|
||||
// 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
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user