命令树优化,测试编辑区域优化
This commit is contained in:
@@ -192,21 +192,26 @@ namespace TestingModule.ViewModels
|
||||
var assembly = Assembly.LoadFrom(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}");
|
||||
// }
|
||||
//}
|
||||
//加载对应的XML注释文件
|
||||
string xmlPath = Path.ChangeExtension(dllPath, ".xml");
|
||||
if (File.Exists(xmlPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load(xmlPath);
|
||||
XmlDocumentCache[assembly.FullName!] = xmlDoc;
|
||||
LoggerHelper.Info($"[XML注释] 成功加载: {Path.GetFileName(xmlPath)} -> 程序集 [{assembly.FullName}]");
|
||||
}
|
||||
catch (Exception xmlEx)
|
||||
{
|
||||
LoggerHelper.Warn($"加载XML注释失败: {Path.GetFileName(xmlPath)} - {xmlEx.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.Warn($"[XML注释] XML文件不存在: {xmlPath}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -284,6 +289,7 @@ namespace TestingModule.ViewModels
|
||||
{
|
||||
Name = subProgram.Name,
|
||||
Tag = subProgram,
|
||||
Tooltip = subProgram.FilePath
|
||||
});
|
||||
}
|
||||
|
||||
@@ -368,6 +374,7 @@ namespace TestingModule.ViewModels
|
||||
{
|
||||
Name = $"{method.Name}({paramText})",
|
||||
Tag = method,
|
||||
Tooltip = GetMethodDocumentation(method),
|
||||
};
|
||||
|
||||
typeNode.Children.Add(methodNode);
|
||||
@@ -433,6 +440,95 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
// 添加获取注释的方法
|
||||
private string? GetMethodDocumentation(MethodInfo method)
|
||||
{
|
||||
if (method.DeclaringType == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
string assemblyName = method.DeclaringType.Assembly.FullName!;
|
||||
if (!_xmlDocumentCache.TryGetValue(assemblyName, out XmlDocument? xmlDoc))
|
||||
{
|
||||
LoggerHelper.Warn($"[XML注释] 缓存未命中: 程序集 [{assemblyName}],缓存包含 { _xmlDocumentCache.Count} 个条目: [{string.Join(", ", _xmlDocumentCache.Keys)}]");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 生成XML文档中的成员ID
|
||||
string memberName = $"M:{method.DeclaringType.FullName}.{method.Name}";
|
||||
var parameters = method.GetParameters();
|
||||
if (parameters.Length > 0)
|
||||
{
|
||||
memberName += "(" + string.Join(",", parameters.Select(p => p.ParameterType.FullName)) + ")";
|
||||
}
|
||||
|
||||
// 查找注释节点
|
||||
XmlNode? memberNode = xmlDoc.SelectSingleNode($"//member[@name='{memberName}']");
|
||||
if (memberNode == null)
|
||||
{
|
||||
LoggerHelper.Warn($"[XML注释] 节点未找到: {memberName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取摘要(summary)
|
||||
var summaryNode = memberNode.SelectSingleNode("summary");
|
||||
string documentation = "";
|
||||
|
||||
if (summaryNode != null)
|
||||
{
|
||||
documentation += CleanXmlContent(summaryNode.InnerXml);
|
||||
}
|
||||
|
||||
// 获取参数注释(param)
|
||||
var paramNodes = memberNode.SelectNodes("param");
|
||||
if (paramNodes != null && paramNodes.Count > 0)
|
||||
{
|
||||
documentation += "\n\n参数:";
|
||||
foreach (XmlNode paramNode in paramNodes)
|
||||
{
|
||||
string? paramName = paramNode.Attributes?["name"]?.Value;
|
||||
if (!string.IsNullOrEmpty(paramName))
|
||||
{
|
||||
documentation += $"\n • {paramName}: {CleanXmlContent(paramNode.InnerXml)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取返回值注释(returns)
|
||||
var returnsNode = memberNode.SelectSingleNode("returns");
|
||||
if (returnsNode != null)
|
||||
{
|
||||
documentation += $"\n\n返回值: {CleanXmlContent(returnsNode.InnerXml)}";
|
||||
}
|
||||
|
||||
return string.IsNullOrWhiteSpace(documentation)
|
||||
? null
|
||||
: System.Net.WebUtility.HtmlDecode(documentation.Trim());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Warn($"获取注释失败: {method.Name} - {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:清理XML内容
|
||||
private string CleanXmlContent(string xmlContent)
|
||||
{
|
||||
return xmlContent
|
||||
.Replace("<see cref=\"", "")
|
||||
.Replace("\"/>", "")
|
||||
.Replace("<para>", "\n")
|
||||
.Replace("</para>", "")
|
||||
.Replace("<seealso", "")
|
||||
.Replace("/>", "")
|
||||
.Replace("<c>", "") // 处理代码标签
|
||||
.Replace("</c>", "")
|
||||
.Replace("<code>", "")
|
||||
.Replace("</code>", "")
|
||||
.Trim();
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 指令添加
|
||||
|
||||
|
||||
@@ -178,10 +178,15 @@ namespace TestingModule.ViewModels
|
||||
|
||||
private void SelectionChanged(object parameter)
|
||||
{
|
||||
var selectedList = parameter as IList;
|
||||
if (selectedList != null)
|
||||
if (parameter is IList list && list.Count > 0)
|
||||
{
|
||||
SelectedItems = selectedList.Cast<StepVM>().ToList();
|
||||
SelectedItems = list.Cast<StepVM>().ToList();
|
||||
}
|
||||
else if (parameter is IEnumerable enumerable && parameter is not string)
|
||||
{
|
||||
var items = enumerable.Cast<StepVM>().ToList();
|
||||
if (items.Count > 0)
|
||||
SelectedItems = items;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,13 +205,19 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
private void CopyStep()
|
||||
{
|
||||
if (_globalInfo.IsAdmin && SelectedItems.Any())
|
||||
if (!_globalInfo.IsAdmin) return;
|
||||
|
||||
// 优先用多选列表,回退到单选
|
||||
var source = (SelectedItems != null && SelectedItems.Any())
|
||||
? SelectedItems
|
||||
: (SelectedStep != null ? new List<StepVM> { SelectedStep } : null);
|
||||
|
||||
if (source == null || !source.Any()) return;
|
||||
|
||||
tmpCopyList.Clear();
|
||||
foreach (var item in source)
|
||||
{
|
||||
tmpCopyList.Clear();
|
||||
foreach (var item in SelectedItems)
|
||||
{
|
||||
tmpCopyList.Add(item);
|
||||
}
|
||||
tmpCopyList.Add(item);
|
||||
}
|
||||
}
|
||||
private void PasteStep()
|
||||
@@ -243,31 +254,29 @@ namespace TestingModule.ViewModels
|
||||
}
|
||||
private void DeleteStep()
|
||||
{
|
||||
// 确保有选中的项
|
||||
if (_globalInfo.IsAdmin && SelectedItems != null && SelectedItems.Any())
|
||||
if (!_globalInfo.IsAdmin) return;
|
||||
|
||||
// 优先用多选列表,回退到单选
|
||||
var source = (SelectedItems != null && SelectedItems.Any())
|
||||
? SelectedItems.ToList()
|
||||
: (SelectedStep != null ? new List<StepVM> { SelectedStep } : null);
|
||||
|
||||
if (source == null || !source.Any()) return;
|
||||
|
||||
foreach (var item in source)
|
||||
{
|
||||
// 创建一个副本进行循环,防止在 Remove 过程中集合变化导致的问题
|
||||
var toDelete = SelectedItems.ToList();
|
||||
_eventAggregator.GetEvent<DeletedStepEvent>().Publish(item.ID);
|
||||
|
||||
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;
|
||||
if (_ScopedContext.SelectedStepList == "主程序")
|
||||
Program.StepCollection.Remove(item);
|
||||
else if (_ScopedContext.SelectedStepList == "错误程序")
|
||||
Program.ErrorStepCollection.Remove(item);
|
||||
}
|
||||
|
||||
// 清空 ViewModel 的选中状态,避免悬挂引用
|
||||
SelectedStep = null;
|
||||
SelectedItems?.Clear();
|
||||
_ScopedContext.SelectedStep = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -313,6 +322,7 @@ namespace TestingModule.ViewModels
|
||||
/// </summary>
|
||||
private void OnSubProgramNavigate(SubProgramNavigatePayload payload)
|
||||
{
|
||||
if (_ScopedContext == null || payload == null) return;
|
||||
var nav = payload.IsErrorProgram ? _ScopedContext.ErrorNav : _ScopedContext.MainNav;
|
||||
if (payload.Action == NavigateAction.Enter && payload.SubProgram != null)
|
||||
{
|
||||
@@ -381,6 +391,12 @@ namespace TestingModule.ViewModels
|
||||
UnsubscribeStepCollections();
|
||||
SubscribeStepCollections();
|
||||
|
||||
// 通知 UI 刷新 DisplaySteps(导航状态虽然引用同一 Program,但集合实例已变)
|
||||
RaisePropertyChanged(nameof(MainDisplaySteps));
|
||||
RaisePropertyChanged(nameof(ErrorDisplaySteps));
|
||||
RaisePropertyChanged(nameof(MainCurrentProgram));
|
||||
RaisePropertyChanged(nameof(ErrorCurrentProgram));
|
||||
|
||||
// 集合被整体替换后,对新集合重新编号
|
||||
Application.Current?.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
@@ -433,7 +449,7 @@ namespace TestingModule.ViewModels
|
||||
Program.PropertyChanged -= Program_PropertyChanged;
|
||||
}
|
||||
|
||||
// 3. 【核心修复】必须显式退订 Prism 全局事件
|
||||
// 3. 显式退订全局 Prism 事件
|
||||
_eventAggregator?.GetEvent<AlarmEvent>()?.Unsubscribe(null);
|
||||
_eventAggregator?.GetEvent<SubProgramNavigateEvent>()?.Unsubscribe(null);
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
<TreeView.Resources>
|
||||
<HierarchicalDataTemplate DataType="{x:Type model:InstructionNodeVM}"
|
||||
ItemsSource="{Binding Children}">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
<TextBlock Text="{Binding Name}" ToolTip="{Binding Tooltip}"/>
|
||||
|
||||
</HierarchicalDataTemplate>
|
||||
</TreeView.Resources>
|
||||
<!-- 双击 -->
|
||||
|
||||
Reference in New Issue
Block a user