diff --git a/Library/FlowNode/MethodDetails.cs b/Library/FlowNode/MethodDetails.cs
index 8293ecb..ee07104 100644
--- a/Library/FlowNode/MethodDetails.cs
+++ b/Library/FlowNode/MethodDetails.cs
@@ -216,8 +216,8 @@ namespace Serein.Library
MethodName = this.MethodName,
MethodAnotherName = this.MethodAnotherName,
NodeType = this.MethodDynamicType.ToString(),
- ParameterDetailsInfos = this.ParameterDetailss.Select(p => p.ToInfo()).ToArray(),
- ReturnTypeFullName = this.ReturnType.FullName,
+ ParameterDetailsInfos = this.ParameterDetailss?.Select(p => p.ToInfo()).ToArray(),
+ ReturnTypeFullName = this.ReturnType?.FullName,
IsParamsArgIndex = this.ParamsArgIndex,
};
}
diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs
index 7577c5f..c6e1f37 100644
--- a/Library/FlowNode/ParameterDetails.cs
+++ b/Library/FlowNode/ParameterDetails.cs
@@ -174,9 +174,9 @@ namespace Serein.Library
IsParams = this.IsParams,
DataTypeFullName = this.DataType.FullName,
Name = this.Name,
- ExplicitTypeFullName = this.ExplicitType.FullName,
+ ExplicitTypeFullName = this.ExplicitType?.FullName,
InputType = this.InputType.ToString(),
- Items = this.Items.Select(it => it).ToArray(),
+ Items = this.Items?.Select(it => it).ToArray(),
};
}
diff --git a/Library/Utils/ConvertHelper.cs b/Library/Utils/ConvertHelper.cs
index 4fc56f2..ba9b238 100644
--- a/Library/Utils/ConvertHelper.cs
+++ b/Library/Utils/ConvertHelper.cs
@@ -200,6 +200,10 @@ namespace Serein.Library.Utils
///
public static T ValueParse(object value) where T : struct, IComparable
{
+ if (value is T data)
+ {
+ return data;
+ }
string valueStr = value.ToString();
return valueStr.ToValueData() ;
}
@@ -228,7 +232,8 @@ namespace Serein.Library.Utils
{
if (string.IsNullOrEmpty(valueStr))
{
- return default(T);
+ throw new NullReferenceException();
+ //return default(T);
}
var type = typeof(T);
object result;
diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs
index 0a59a2d..30d5fe8 100644
--- a/NodeFlow/Env/FlowEnvironment.cs
+++ b/NodeFlow/Env/FlowEnvironment.cs
@@ -1048,7 +1048,9 @@ namespace Serein.NodeFlow.Env
return Task.FromResult(null);
}
NodeModelBase? nodeModel;
- if (methodDetailsInfo is null)
+ if (methodDetailsInfo is null
+ || string.IsNullOrEmpty(methodDetailsInfo.AssemblyName)
+ || string.IsNullOrEmpty(methodDetailsInfo.MethodName))
{
nodeModel = FlowNodeExtension.CreateNode(this, nodeControlType); // 加载基础节点
}
diff --git a/NodeFlow/Model/SingleScriptNode.cs b/NodeFlow/Model/SingleScriptNode.cs
index 3912158..3a53cea 100644
--- a/NodeFlow/Model/SingleScriptNode.cs
+++ b/NodeFlow/Model/SingleScriptNode.cs
@@ -12,6 +12,7 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
+using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Serein.NodeFlow.Model
{
@@ -246,12 +247,29 @@ namespace Serein.NodeFlow.Model
{
public static DateTime GetNow() => DateTime.Now;
+
+ #region 常用的类型转换
+ public static bool BoolOf(object value)
+ {
+ return ConvertHelper.ValueParse(value);
+ }
+ public static int IntOf(object value)
+ {
+ return ConvertHelper.ValueParse(value);
+ }
+ public static int LongOf(object value)
+ {
+ return ConvertHelper.ValueParse(value);
+ }
+
+
+ #endregion
+
public static Type TypeOf(object type)
{
return type.GetType();
}
-
public static void Print(object value)
{
SereinEnv.WriteLine(InfoType.INFO, value?.ToString());
diff --git a/Workbench/App.xaml.cs b/Workbench/App.xaml.cs
index 708ae32..7e3d60d 100644
--- a/Workbench/App.xaml.cs
+++ b/Workbench/App.xaml.cs
@@ -32,9 +32,11 @@ namespace Serein.Workbench
collection.AddSingleton();
collection.AddSingleton();
collection.AddSingleton();
+ collection.AddSingleton();
+ collection.AddSingleton();
collection.AddTransient(); // 画布
- collection.AddTransient(); // 画布节点树视图
+ collection.AddTransient(); // 画布节点树视图
}
public static void AddWorkbenchServices(this IServiceCollection collection)
@@ -42,6 +44,7 @@ namespace Serein.Workbench
collection.AddSingleton(); // 流程事件管理
collection.AddSingleton();// 按键事件管理
collection.AddSingleton(); // 流程事件管理
+ collection.AddSingleton(); // 项目管理
collection.AddSingleton(); // 节点操作管理
}
@@ -104,69 +107,45 @@ namespace Serein.Workbench
collection.AddViewModelServices();
var services = collection.BuildServiceProvider(); // 绑定并返回获取实例的服务接口
App.ServiceProvider = services;
-
-
-
-
+#if DEBUG
_ = this.LoadLocalProjectAsync();
-
- }
-
-
-
- private async Task LoadLocalProjectAsync()
- {
- await Task.Delay(500);
-#if DEBUG
- if (1 == 1)
- {
- // 这里是测试代码,可以删除
- string filePath;
- filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\Release\net8.0\PLCproject.dnf";
- filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\Release\banyunqi\project.dnf";
- filePath = @"F:\临时\project\project.dnf";
- filePath = @"F:\TempFile\flow\qrcode\project.dnf";
- filePath = @"F:\TempFile\flow\temp2\project.dnf";
- if (File.Exists(filePath))
- {
- string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
- App.FlowProjectData = JsonConvert.DeserializeObject(content);
- App.FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
- var dir = Path.GetDirectoryName(filePath);
- App.GetService().LoadProject(new FlowEnvInfo { Project = App.FlowProjectData }, App.FileDataPath);
- }
-
-
- }
#endif
}
-
+#if DEBUG
+
+ // 这里是测试代码,可以删除
+ private async Task LoadLocalProjectAsync()
+ {
+ var projectService = App.GetService();
+ await Task.Delay(500);
+ if (1 == 1)
+ {
+ string filePath;
+ filePath = @"F:\TempFile\flow\temp2\project.dnf";
+ projectService.LoadLocalProject(filePath);
+ }
+
+ }
+#endif
- public static SereinProjectData? FlowProjectData { get; set; }
- public static string FileDataPath { get; set; } = "";
private async void Application_Startup(object sender, StartupEventArgs e)
{
- // 检查是否传入了参数
+ var projectService = App.GetService();
if (e.Args.Length == 1)
{
- // 获取文件路径
string filePath = e.Args[0];
- // 检查文件是否存在
- if (!System.IO.File.Exists(filePath))
+ if (!System.IO.File.Exists(filePath)) // 检查文件是否存在
{
MessageBox.Show($"文件未找到:{filePath}");
Shutdown(); // 关闭应用程序
return;
}
-
try
{
// 读取文件内容
- string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
- FlowProjectData = JsonConvert.DeserializeObject(content);
- FileDataPath = System.IO.Path.GetDirectoryName(filePath) ?? "";
+ projectService.LoadLocalProject(filePath);
}
catch (Exception ex)
{
diff --git a/Workbench/Customs/FlowMethodInfoListBox.xaml b/Workbench/Customs/FlowMethodInfoListBox.xaml
index 68e67d0..7c215cd 100644
--- a/Workbench/Customs/FlowMethodInfoListBox.xaml
+++ b/Workbench/Customs/FlowMethodInfoListBox.xaml
@@ -11,7 +11,8 @@
-
diff --git a/Workbench/Customs/FlowMethodInfoListBox.xaml.cs b/Workbench/Customs/FlowMethodInfoListBox.xaml.cs
index 40d89b1..30df405 100644
--- a/Workbench/Customs/FlowMethodInfoListBox.xaml.cs
+++ b/Workbench/Customs/FlowMethodInfoListBox.xaml.cs
@@ -1,6 +1,7 @@
using Serein.Library;
using Serein.Library.Utils;
using Serein.Workbench.Models;
+using Serein.Workbench.Services;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -39,9 +40,23 @@ namespace Serein.Workbench.Customs
///
/// FlowMethodInfoListBox.xaml 的交互逻辑
///
- public partial class FlowMethodInfoListBox : UserControl
+ public partial class FlowMethodInfoListBox : UserControl,System.ComponentModel.INotifyPropertyChanged
{
+ private object viewMethodInfo;
+ public object ViewMethodInfo
+ {
+ get => viewMethodInfo;
+ set
+ {
+ if (viewMethodInfo != value)
+ {
+ viewMethodInfo = value;
+ PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(ViewMethodInfo)));
+ }
+ }
+ }
+ public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public FlowMethodInfoListBox()
{
@@ -130,5 +145,20 @@ namespace Serein.Workbench.Customs
}
}
+ private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if(sender is ListBox listBox)
+ {
+ if (listBox.SelectedIndex != -1)
+ {
+ var item = listBox.SelectedItem;
+ if (item is MethodDetailsInfo mdInfo)
+ {
+ App.GetService().CurrentMethodDetailsInfo = mdInfo;
+ }
+ }
+ // Serein.Workbench.Models.FlowLibraryInfo
+ }
+ }
}
}
diff --git a/Workbench/Node/View/ActionNodeControl.xaml b/Workbench/Node/View/ActionNodeControl.xaml
index 8515fd3..69ad89d 100644
--- a/Workbench/Node/View/ActionNodeControl.xaml
+++ b/Workbench/Node/View/ActionNodeControl.xaml
@@ -64,7 +64,7 @@
-
+
diff --git a/Workbench/Node/View/ConditionNodeControl.xaml b/Workbench/Node/View/ConditionNodeControl.xaml
index ec950e3..ff302ea 100644
--- a/Workbench/Node/View/ConditionNodeControl.xaml
+++ b/Workbench/Node/View/ConditionNodeControl.xaml
@@ -39,7 +39,7 @@
-
+
diff --git a/Workbench/Node/View/ConditionNodeControl.xaml.cs b/Workbench/Node/View/ConditionNodeControl.xaml.cs
index 950bab1..36bcaae 100644
--- a/Workbench/Node/View/ConditionNodeControl.xaml.cs
+++ b/Workbench/Node/View/ConditionNodeControl.xaml.cs
@@ -17,13 +17,14 @@ namespace Serein.Workbench.Node.View
base.ViewModel = new ConditionNodeControlViewModel (new SingleConditionNode(env));
base.ViewModel.IsEnabledOnView = false;
DataContext = ViewModel;
-
+ base.ViewModel.NodeModel.DisplayName = "[条件节点]";
InitializeComponent();
}
public ConditionNodeControl(ConditionNodeControlViewModel viewModel):base(viewModel)
{
DataContext = viewModel;
+ viewModel.NodeModel.DisplayName = "[条件节点]";
InitializeComponent();
}
diff --git a/Workbench/Node/View/ExpOpNodeControl.xaml b/Workbench/Node/View/ExpOpNodeControl.xaml
index c6e25ed..ac59910 100644
--- a/Workbench/Node/View/ExpOpNodeControl.xaml
+++ b/Workbench/Node/View/ExpOpNodeControl.xaml
@@ -27,7 +27,7 @@
-
+
diff --git a/Workbench/Node/View/ExpOpNodeControl.xaml.cs b/Workbench/Node/View/ExpOpNodeControl.xaml.cs
index bfd7369..b14f140 100644
--- a/Workbench/Node/View/ExpOpNodeControl.xaml.cs
+++ b/Workbench/Node/View/ExpOpNodeControl.xaml.cs
@@ -15,12 +15,14 @@ namespace Serein.Workbench.Node.View
var env = App.GetService();
ViewModel = new ExpOpNodeControlViewModel(new SingleExpOpNode(env));
base.ViewModel.IsEnabledOnView = false;
+ base.ViewModel.NodeModel.DisplayName = "[表达式]";
DataContext = ViewModel;
InitializeComponent();
}
public ExpOpNodeControl(ExpOpNodeControlViewModel viewModel) :base(viewModel)
{
DataContext = viewModel;
+ viewModel.NodeModel.DisplayName = "[表达式]";
InitializeComponent();
}
diff --git a/Workbench/Node/View/GlobalDataControl.xaml b/Workbench/Node/View/GlobalDataControl.xaml
index 481dacb..d13189a 100644
--- a/Workbench/Node/View/GlobalDataControl.xaml
+++ b/Workbench/Node/View/GlobalDataControl.xaml
@@ -37,7 +37,7 @@
-
+
diff --git a/Workbench/Node/View/GlobalDataControl.xaml.cs b/Workbench/Node/View/GlobalDataControl.xaml.cs
index bdf7018..75c8fee 100644
--- a/Workbench/Node/View/GlobalDataControl.xaml.cs
+++ b/Workbench/Node/View/GlobalDataControl.xaml.cs
@@ -16,6 +16,7 @@ namespace Serein.Workbench.Node.View
var env = App.GetService();
base.ViewModel = new GlobalDataNodeControlViewModel(new SingleGlobalDataNode(env));
base.ViewModel.IsEnabledOnView = false;
+ base.ViewModel.NodeModel.DisplayName = "[全局数据]";
DataContext = ViewModel;
InitializeComponent();
}
@@ -23,6 +24,7 @@ namespace Serein.Workbench.Node.View
public GlobalDataControl(GlobalDataNodeControlViewModel viewModel) : base(viewModel)
{
DataContext = viewModel;
+ viewModel.NodeModel.DisplayName = "[全局数据]";
InitializeComponent();
}
diff --git a/Workbench/Node/View/ScriptNodeControl.xaml.cs b/Workbench/Node/View/ScriptNodeControl.xaml.cs
index 5dfb829..5fb0ae7 100644
--- a/Workbench/Node/View/ScriptNodeControl.xaml.cs
+++ b/Workbench/Node/View/ScriptNodeControl.xaml.cs
@@ -73,7 +73,8 @@ namespace Serein.Workbench.Node.View
// 获取 MethodDetailsControl 实例
var methodDetailsControl = this.MethodDetailsControl;
var itemsControl = FindVisualChild(methodDetailsControl); // 查找 ItemsControl
- if (itemsControl != null)
+
+ if (itemsControl != null && base.ViewModel.NodeModel.MethodDetails != null)
{
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
var controls = new List();
diff --git a/Workbench/Node/View/UINodeControl.xaml b/Workbench/Node/View/UINodeControl.xaml
index 3c3621a..9c5ec8f 100644
--- a/Workbench/Node/View/UINodeControl.xaml
+++ b/Workbench/Node/View/UINodeControl.xaml
@@ -27,13 +27,14 @@
-
+
+
-
+
diff --git a/Workbench/Node/View/UINodeControl.xaml.cs b/Workbench/Node/View/UINodeControl.xaml.cs
index a7fa9e1..0701389 100644
--- a/Workbench/Node/View/UINodeControl.xaml.cs
+++ b/Workbench/Node/View/UINodeControl.xaml.cs
@@ -26,6 +26,7 @@ namespace Serein.Workbench.Node.View
public UINodeControl()
{
base.ViewModel.IsEnabledOnView = true;
+ base.ViewModel.NodeModel.DisplayName = "[流程UI]";
InitializeComponent();
}
@@ -33,6 +34,7 @@ namespace Serein.Workbench.Node.View
{
ViewModel = viewModel;
DataContext = viewModel;
+ ViewModel.NodeModel.DisplayName = "[流程UI]";
InitializeComponent();
diff --git a/Workbench/Services/FlowNodeService.cs b/Workbench/Services/FlowNodeService.cs
index 362abe6..cb0e71a 100644
--- a/Workbench/Services/FlowNodeService.cs
+++ b/Workbench/Services/FlowNodeService.cs
@@ -9,6 +9,7 @@ using Serein.Workbench.Node.ViewModel;
using Serein.Workbench.ViewModels;
using Serein.Workbench.Views;
using System;
+using System.Reactive;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@@ -20,7 +21,7 @@ namespace Serein.Workbench.Services
///
/// 流程节点管理
///
- public class FlowNodeService
+ public class FlowNodeService
{
@@ -44,6 +45,16 @@ namespace Serein.Workbench.Services
///
public Action OnViewCanvasChanged{ get; set; }
+ ///
+ /// 查看的节点发生变化
+ ///
+ public Action OnViewNodeControlChanged{ get; set; }
+
+ ///
+ /// 查看方法发生变化
+ ///
+ public Action OnViewMethodDetailsInfoChanged { get; set; }
+
#endregion
#region 创建节点相关的属性
@@ -64,10 +75,39 @@ namespace Serein.Workbench.Services
}
}
+
+ private NodeControlBase? currentSelectNodeControl;
+
+ ///
+ /// 当前选中的节点
+ ///
+ public NodeControlBase? CurrentSelectNodeControl { get => currentSelectNodeControl; set
+ {
+ if (value == null || value.Equals(currentSelectNodeControl))
+ {
+ return;
+ }
+ currentSelectNodeControl = value;
+ OnViewNodeControlChanged?.Invoke(value);
+ }
+ }
+
+ private MethodDetailsInfo? currentMethodDetailsInfo;
+
///
/// 当前拖动的方法信息
///
- public MethodDetailsInfo? CurrentDragMdInfo { get; set; }
+ public MethodDetailsInfo? CurrentMethodDetailsInfo { get => currentMethodDetailsInfo; set
+ {
+ if (value == null || value.Equals(currentMethodDetailsInfo))
+ {
+ return;
+ }
+ currentMethodDetailsInfo = value;
+ OnViewMethodDetailsInfoChanged?.Invoke(value);
+ }
+ }
+
///
/// 当前需要创建的节点类型
@@ -79,10 +119,6 @@ namespace Serein.Workbench.Services
///
public PositionOfUI? CurrentMouseLocation { get; set; }
- ///
- /// 当前选中的节点
- ///
- public NodeControlBase? CurrentSelectNodeControl { get; set; }
///
/// 连接数据
@@ -651,7 +687,7 @@ namespace Serein.Workbench.Services
string canvasGuid = model.Guid;
NodeControlType nodeType = CurrentNodeControlType;
PositionOfUI? position = CurrentMouseLocation;
- MethodDetailsInfo? methodDetailsInfo = CurrentDragMdInfo;
+ MethodDetailsInfo? methodDetailsInfo = CurrentMethodDetailsInfo;
if (position is null)
{
diff --git a/Workbench/Services/FlowProjectService.cs b/Workbench/Services/FlowProjectService.cs
new file mode 100644
index 0000000..7bc033e
--- /dev/null
+++ b/Workbench/Services/FlowProjectService.cs
@@ -0,0 +1,60 @@
+using Newtonsoft.Json;
+using Serein.Library;
+using Serein.Library.Api;
+using Serein.NodeFlow.Env;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Serein.Workbench.Services
+{
+ public class FlowProjectService
+ {
+ private readonly IFlowEnvironment flowEnvironment;
+
+ public SereinProjectData? FlowProjectData { get; set; }
+ public string FileDataPath { get; set; }
+
+ public FlowProjectService(IFlowEnvironment flowEnvironment)
+ {
+ this.flowEnvironment = flowEnvironment;
+ }
+
+ public void LoadLocalProject(string filePath)
+ {
+ if (File.Exists(filePath))
+ {
+ string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
+ this.FlowProjectData = JsonConvert.DeserializeObject(content);
+ this.FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
+ var dir = Path.GetDirectoryName(filePath);
+ var flowEnvInfo = new FlowEnvInfo
+ {
+ Project = FlowProjectData,
+ };
+ flowEnvironment.LoadProject(flowEnvInfo, FileDataPath);
+ }
+ }
+
+ public void SelectProjectFile()
+ {
+ System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
+ openFileDialog.Filter = "流程项目文件|*.dnf|所有文件|*.*";
+ openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ openFileDialog.Title = "打开项目文件";
+ openFileDialog.Multiselect = false;
+
+ // 显示文件对话框
+ if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+ {
+ // 获取用户选择的文件路径
+ var projectFile = openFileDialog.FileName;
+ LoadLocalProject(projectFile);
+ }
+ }
+
+ }
+}
diff --git a/Workbench/ViewModels/Locator.cs b/Workbench/ViewModels/Locator.cs
index 322d6f1..7ac6170 100644
--- a/Workbench/ViewModels/Locator.cs
+++ b/Workbench/ViewModels/Locator.cs
@@ -22,11 +22,13 @@ namespace Serein.Workbench.ViewModels
public BaseNodesViewModel BaseNodesViewModel => App.GetService() ?? throw new NotImplementedException();
public FlowLibrarysViewModel FlowLibrarysViewModel => App.GetService() ?? throw new NotImplementedException();
public FlowEditViewModel FlowEditViewModel => App.GetService() ?? throw new NotImplementedException();
+ public ViewNodeInfoViewModel NodeInfoViewModel => App.GetService() ?? throw new NotImplementedException();
+ public ViewNodeMethodInfoViewModel ViewNodeMethodInfoViewModel => App.GetService() ?? throw new NotImplementedException();
public FlowCanvasViewModel FlowCanvasViewModel => App.GetService() ?? throw new NotImplementedException();
- public CanvasInfoViewModel CanvasNodeTreeViewModel => App.GetService() ?? throw new NotImplementedException();
+ public ViewCanvasInfoViewModel CanvasNodeTreeViewModel => App.GetService() ?? throw new NotImplementedException();
public IServiceProvider ServiceProvider { get; }
}
diff --git a/Workbench/ViewModels/MainMenuBarViewModel.cs b/Workbench/ViewModels/MainMenuBarViewModel.cs
index fa08066..2701fa8 100644
--- a/Workbench/ViewModels/MainMenuBarViewModel.cs
+++ b/Workbench/ViewModels/MainMenuBarViewModel.cs
@@ -10,6 +10,7 @@ namespace Serein.Workbench.ViewModels
{
private readonly IFlowEnvironment environment;
private readonly FlowNodeService flowNodeService;
+ private readonly FlowProjectService flowProjectService;
///
/// 保存项目
@@ -61,10 +62,13 @@ namespace Serein.Workbench.ViewModels
- public MainMenuBarViewModel(IFlowEnvironment environment, FlowNodeService flowNodeService)
+ public MainMenuBarViewModel(IFlowEnvironment environment,
+ FlowNodeService flowNodeService,
+ FlowProjectService flowProjectService)
{
this.environment = environment;
this.flowNodeService = flowNodeService;
+ this.flowProjectService = flowProjectService;
SaveProjectCommand = new RelayCommand(SaveProject); // 保存项目
LoadLocalProjectCommand = new RelayCommand(LoadLocalProject); // 加载本地项目
LoadRemoteProjectCommand = new RelayCommand(LoadRemoteProject); // 加载远程项目
@@ -78,12 +82,16 @@ namespace Serein.Workbench.ViewModels
OpenEnvOutWindowCommand = new RelayCommand(OpenEnvOutWindow); // 打开运行输出窗口
OpenDynamicCompilerCommand = new RelayCommand(OpenDynamicCompiler); // 打开动态编译仓库窗口
+ this.flowProjectService = flowProjectService;
}
private void SaveProject() => environment.SaveProject(); // 保存项目
private void LoadLocalProject() {
- //environment.LoadProject(); // 加载项目
+
+ flowProjectService.SelectProjectFile(); //选择项目
}
+
+
private void LoadRemoteProject()
{
}
@@ -91,7 +99,7 @@ namespace Serein.Workbench.ViewModels
private void RemoteFlowCanvas() => flowNodeService.RemoveFlowCanvas();
- private void StartFlow() => environment.StartFlowAsync([.. flowNodeService.FlowCanvass.Select(c => c.Guid)]);
+ private void StartUIFlow() => environment.StartFlowAsync([.. flowNodeService.FlowCanvass.Select(c => c.Guid)]);
private void StartCurrentCanvasFlow() => environment.StartFlowAsync([flowNodeService.CurrentSelectCanvas.Guid]);
private void StopCurrentCanvasFlow() { }
private void OpenDynamicCompiler() { }
diff --git a/Workbench/ViewModels/CanvasNodeTreeViewModel.cs b/Workbench/ViewModels/ViewCanvasInfoViewModel.cs
similarity index 86%
rename from Workbench/ViewModels/CanvasNodeTreeViewModel.cs
rename to Workbench/ViewModels/ViewCanvasInfoViewModel.cs
index 0155c38..eed4617 100644
--- a/Workbench/ViewModels/CanvasNodeTreeViewModel.cs
+++ b/Workbench/ViewModels/ViewCanvasInfoViewModel.cs
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace Serein.Workbench.ViewModels
{
- internal partial class CanvasInfoViewModel : ObservableObject
+ internal partial class ViewCanvasInfoViewModel : ObservableObject
{
private readonly FlowNodeService flowNodeService;
@@ -20,7 +20,7 @@ namespace Serein.Workbench.ViewModels
[ObservableProperty]
private FlowCanvasDetails _model;
- public CanvasInfoViewModel(FlowNodeService flowNodeService)
+ public ViewCanvasInfoViewModel(FlowNodeService flowNodeService)
{
this.flowNodeService = flowNodeService;
this.flowNodeService.OnViewCanvasChanged += OnViewCanvasChanged;
@@ -34,5 +34,8 @@ namespace Serein.Workbench.ViewModels
{
Model = flowCanvas.ViewModel.Model;
}
+
+
+
}
}
diff --git a/Workbench/ViewModels/ViewNodeInfoViewModel.cs b/Workbench/ViewModels/ViewNodeInfoViewModel.cs
new file mode 100644
index 0000000..1b63962
--- /dev/null
+++ b/Workbench/ViewModels/ViewNodeInfoViewModel.cs
@@ -0,0 +1,46 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using Serein.Library;
+using Serein.Workbench.Node.View;
+using Serein.Workbench.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Serein.Workbench.ViewModels
+{
+ internal partial class ViewNodeInfoViewModel : ObservableObject
+ {
+ private readonly FlowNodeService flowNodeService;
+
+ ///
+ /// 当前预览的节点
+ ///
+ [ObservableProperty]
+ private NodeModelBase viewNodeModel;
+
+ public ViewNodeInfoViewModel(FlowNodeService flowNodeService)
+ {
+ this.flowNodeService = flowNodeService;
+ InitEvent();
+ }
+
+ private void InitEvent()
+ {
+ flowNodeService.OnViewNodeControlChanged += OnViewNodeControlChanged;
+ }
+ private void OnViewNodeControlChanged(NodeControlBase viewNodeControl)
+ {
+ if(viewNodeControl is null)
+ {
+ ViewNodeModel = null;
+ }
+ else
+ {
+ ViewNodeModel = viewNodeControl.ViewModel.NodeModel;
+ }
+
+ }
+ }
+}
diff --git a/Workbench/ViewModels/ViewNodeMethodInfoViewModel.cs b/Workbench/ViewModels/ViewNodeMethodInfoViewModel.cs
new file mode 100644
index 0000000..4bf56dc
--- /dev/null
+++ b/Workbench/ViewModels/ViewNodeMethodInfoViewModel.cs
@@ -0,0 +1,40 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using Serein.Library;
+using Serein.Workbench.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Serein.Workbench.ViewModels
+{
+ internal partial class ViewNodeMethodInfoViewModel : ObservableObject
+ {
+ private readonly FlowNodeService flowNodeService;
+
+ ///
+ /// 当前预览的节点
+ ///
+ [ObservableProperty]
+ private MethodDetailsInfo mdInfo;
+
+ public ViewNodeMethodInfoViewModel(FlowNodeService flowNodeService)
+ {
+ this.flowNodeService = flowNodeService;
+
+ InitEvent();
+ }
+ private void InitEvent()
+ {
+ flowNodeService.OnViewMethodDetailsInfoChanged += OnViewMethodDetailsInfoChanged;
+ }
+ private void OnViewMethodDetailsInfoChanged(MethodDetailsInfo methodDetailsInfo)
+ {
+ MdInfo = methodDetailsInfo;
+ }
+
+ }
+}
diff --git a/Workbench/Views/BaseNodesView.xaml b/Workbench/Views/BaseNodesView.xaml
index c3429e3..b47227f 100644
--- a/Workbench/Views/BaseNodesView.xaml
+++ b/Workbench/Views/BaseNodesView.xaml
@@ -12,11 +12,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/Workbench/Views/CanvasInfoView.xaml b/Workbench/Views/CanvasInfoView.xaml
deleted file mode 100644
index 7b515e4..0000000
--- a/Workbench/Views/CanvasInfoView.xaml
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Workbench/Views/FlowCanvasView.xaml.cs b/Workbench/Views/FlowCanvasView.xaml.cs
index 975e07a..5aff73a 100644
--- a/Workbench/Views/FlowCanvasView.xaml.cs
+++ b/Workbench/Views/FlowCanvasView.xaml.cs
@@ -40,6 +40,7 @@ using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using UserControl = System.Windows.Controls.UserControl;
using Clipboard = System.Windows.Clipboard;
using TextDataFormat = System.Windows.TextDataFormat;
+using System.Windows.Media.Animation;
namespace Serein.Workbench.Views
{
@@ -119,7 +120,7 @@ namespace Serein.Workbench.Views
private readonly TranslateTransform translateTransform;
#endregion
- #region 初始化以及相关事件
+ #region 初始化
public FlowCanvasView(FlowCanvasDetails model)
{
@@ -128,12 +129,13 @@ namespace Serein.Workbench.Views
this.DataContext = vm;
InitializeComponent();
+
flowEnvironment = App.GetService();
flowNodeService = App.GetService();
keyEventService = App.GetService();
flowEEForwardingService = App.GetService();
- flowNodeService.OnCreateNode += OnCreateNode;
- keyEventService.OnKeyDown += KeyEventService_OnKeyDown;
+
+
//flowEEForwardingService.OnProjectLoaded += FlowEEForwardingService_OnProjectLoaded;
// 缩放平移容器
@@ -144,17 +146,10 @@ namespace Serein.Workbench.Views
canvasTransformGroup.Children.Add(translateTransform);
FlowChartCanvas.RenderTransform = canvasTransformGroup;
SetBinding(model);
-
+ InitEvent();
}
-
- private void FlowEEForwardingService_OnProjectLoaded(ProjectLoadedEventArgs eventArgs)
- {
- RefreshAllLine();
- }
-
-
///
/// 设置绑定
///
@@ -162,12 +157,12 @@ namespace Serein.Workbench.Views
private void SetBinding(FlowCanvasDetails canvasModel)
{
Binding bindingScaleX = new(nameof(canvasModel.ScaleX)) { Source = canvasModel, Mode = BindingMode.TwoWay };
- BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleXProperty, bindingScaleX);
+ BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleXProperty, bindingScaleX);
- Binding bindingScaleY = new(nameof(canvasModel.ScaleY)){ Source = canvasModel, Mode = BindingMode.TwoWay };
+ Binding bindingScaleY = new(nameof(canvasModel.ScaleY)) { Source = canvasModel, Mode = BindingMode.TwoWay };
BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleYProperty, bindingScaleY);
- Binding bindingX = new(nameof(canvasModel.ViewX)) { Source = canvasModel, Mode = BindingMode.TwoWay };
+ Binding bindingX = new(nameof(canvasModel.ViewX)) { Source = canvasModel, Mode = BindingMode.TwoWay };
BindingOperations.SetBinding(translateTransform, TranslateTransform.XProperty, bindingX);
Binding bindingY = new(nameof(canvasModel.ViewY)) { Source = canvasModel, Mode = BindingMode.TwoWay };
@@ -176,17 +171,114 @@ namespace Serein.Workbench.Views
}
+ private void InitEvent()
+ {
+ flowNodeService.OnCreateNode += OnCreateNode;
+ keyEventService.OnKeyDown += KeyEventService_OnKeyDown;
+ flowEEForwardingService.OnNodeLocated += FlowEEForwardingService_OnNodeLocated;
+ }
+
+ ///
+ /// 节点需要定位
+ ///
+ ///
+ ///
+ private void FlowEEForwardingService_OnNodeLocated(NodeLocatedEventArgs eventArgs)
+ {
+ if(!ViewModel.NodeControls.TryGetValue(eventArgs.NodeGuid,out var nodeControl))
+ {
+ return;
+ }
+ /*if (nodeControl.FlowCanvas.Guid.Equals(Guid)) // 防止事件传播到其它画布
+ {
+ return;
+ }*/
+
+ // 获取控件在 FlowChartCanvas 上的相对位置
+#if false
+ Rect controlBounds = VisualTreeHelper.GetDescendantBounds(nodeControl);
+ Point controlPosition = nodeControl.TransformToAncestor(FlowChartCanvas).Transform(new Point(0, 0));
+
+ // 获取控件在画布上的中心点
+ double controlCenterX = controlPosition.X + controlBounds.Width / 2;
+ double controlCenterY = controlPosition.Y + controlBounds.Height / 2;
+
+ // 考虑缩放因素计算目标位置的中心点
+ double scaledCenterX = controlCenterX * scaleTransform.ScaleX;
+ double scaledCenterY = controlCenterY * scaleTransform.ScaleY;
+
+ // 计算平移偏移量,使得控件在可视区域的中心
+ double translateX = scaledCenterX - this.FlowChartStackPanel.ActualWidth / 2;
+ double translateY = scaledCenterY - FlowChartStackPanel.ActualHeight / 2;
+
+ var translate = this.translateTransform;
+ // 应用平移变换
+ translate.X = 0;
+ translate.Y = 0;
+ translate.X -= translateX;
+ translate.Y -= translateY;
+#endif
+
+ // 设置RenderTransform以实现移动效果
+ TranslateTransform translateTransform = new TranslateTransform();
+ nodeControl.RenderTransform = translateTransform;
+ ElasticAnimation(nodeControl, translateTransform, 6, 0.5, 0.5);
+ }
+ ///
+ /// 控件抖动
+ /// 来源:https://www.cnblogs.com/RedSky/p/17705411.html
+ /// 作者:HotSky
+ ///
+ ///
+ /// 需要抖动的控件
+ /// 抖动第一下偏移量
+ /// 减弱幅度(小于等于power,大于0)
+ /// 持续系数(大于0),越大时间越长,
+ private static void ElasticAnimation(NodeControlBase nodeControl, TranslateTransform translate, double power, double range = 1, double speed = 1)
+ {
+ DoubleAnimationUsingKeyFrames animation1 = new DoubleAnimationUsingKeyFrames();
+ for (double i = power, j = 1; i >= 0; i -= range)
+ {
+ animation1.KeyFrames.Add(new LinearDoubleKeyFrame(-i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
+ animation1.KeyFrames.Add(new LinearDoubleKeyFrame(i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
+ }
+ translate.BeginAnimation(TranslateTransform.YProperty, animation1);
+ DoubleAnimationUsingKeyFrames animation2 = new DoubleAnimationUsingKeyFrames();
+ for (double i = power, j = 1; i >= 0; i -= range)
+ {
+ animation2.KeyFrames.Add(new LinearDoubleKeyFrame(-i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
+ animation2.KeyFrames.Add(new LinearDoubleKeyFrame(i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
+ }
+ translate.BeginAnimation(TranslateTransform.XProperty, animation2);
+
+ animation2.Completed += (s, e) =>
+ {
+ nodeControl.RenderTransform = null; // 或者重新设置为默认值
+ };
+ }
+
+
+ ///
+ /// 加载完成后刷新显示
+ ///
+ ///
+ private void FlowEEForwardingService_OnProjectLoaded(ProjectLoadedEventArgs eventArgs)
+ {
+ RefreshAllLine();
+ }
+
+
+
///
/// 当前画布创建了节点
///
///
private void OnCreateNode(NodeControlBase nodeControl)
{
- if (!nodeControl.FlowCanvas.Guid.Equals(Guid))
- {
- // 防止事件传播到其它画布
- return;
- }
+ if (!nodeControl.FlowCanvas.Guid.Equals(Guid)) // 防止事件传播到其它画布
+ {
+ return;
+ }
var p = nodeControl.ViewModel.NodeModel.Position;
PositionOfUI position = new PositionOfUI(p.X, p.Y);
if (TryPlaceNodeInRegion(nodeControl, position, out var regionControl)) // 判断添加到区域容器
@@ -223,14 +315,14 @@ namespace Serein.Workbench.Views
// 准备放置条件表达式控件
if (nodeControl.ViewModel.NodeModel.ControlType == NodeControlType.ExpCondition)
{
- /* ConditionRegionControl? conditionRegion = WpfFuncTool.GetParentOfType(hitElement);
- if (conditionRegion is not null)
- {
- targetNodeControl = conditionRegion;
- //// 如果存在条件区域容器
- //conditionRegion.AddCondition(nodeControl);
- return true;
- }*/
+ /* ConditionRegionControl? conditionRegion = WpfFuncTool.GetParentOfType(hitElement);
+ if (conditionRegion is not null)
+ {
+ targetNodeControl = conditionRegion;
+ //// 如果存在条件区域容器
+ //conditionRegion.AddCondition(nodeControl);
+ return true;
+ }*/
}
else
@@ -246,11 +338,13 @@ namespace Serein.Workbench.Views
}
targetNodeControl = null;
return false;
- }
-
+ }
#endregion
- #region 画布接口实现
+
+
+
+ #region 接口实现
private IFlowCanvas Api => this;
public string Guid
@@ -273,7 +367,7 @@ namespace Serein.Workbench.Views
}
void IFlowCanvas.Add(NodeControlBase nodeControl)
{
-
+
ViewModel.NodeControls.TryAdd(nodeControl.ViewModel.NodeModel.Guid, nodeControl);
FlowChartCanvas.Dispatcher.Invoke(() =>
@@ -356,7 +450,7 @@ namespace Serein.Workbench.Views
//}
}
}
- void IFlowCanvas.CreateArgConnection(NodeControlBase fromNodeControl, NodeControlBase toNodeControl,ConnectionArgSourceType type, int index)
+ void IFlowCanvas.CreateArgConnection(NodeControlBase fromNodeControl, NodeControlBase toNodeControl, ConnectionArgSourceType type, int index)
{
if (fromNodeControl is not INodeJunction IFormJunction || toNodeControl is not INodeJunction IToJunction)
{
@@ -377,7 +471,8 @@ namespace Serein.Workbench.Views
_ = Task.Run(async () =>
{
await Task.Delay(100);
- await App.UIContextOperation.InvokeAsync(() => {
+ await App.UIContextOperation.InvokeAsync(() =>
+ {
Api.CreateArgConnection(fromNodeControl, toNodeControl, type, index);
});
});
@@ -651,7 +746,7 @@ namespace Serein.Workbench.Views
if (e.Data.GetData(MouseNodeType.CreateDllNodeInCanvas) is MoveNodeModel nodeModel)
{
flowNodeService.CurrentNodeControlType = nodeModel.NodeControlType; // 设置基础节点类型
- flowNodeService.CurrentDragMdInfo = nodeModel.MethodDetailsInfo; // 基础节点不需要参数信息
+ flowNodeService.CurrentMethodDetailsInfo = nodeModel.MethodDetailsInfo; // 基础节点不需要参数信息
flowNodeService.CurrentMouseLocation = position; // 设置当前鼠标为止
flowNodeService.CreateNode(); // 创建来自DLL加载的方法节点
}
@@ -674,7 +769,7 @@ namespace Serein.Workbench.Views
if (nodeControlType != NodeControlType.None)
{
flowNodeService.CurrentNodeControlType = nodeControlType; // 设置基础节点类型
- flowNodeService.CurrentDragMdInfo = null; // 基础节点不需要参数信息
+ flowNodeService.CurrentMethodDetailsInfo = null; // 基础节点不需要参数信息
flowNodeService.CurrentMouseLocation = position; // 设置当前鼠标为止
flowNodeService.CreateNode(); // 创建基础节点
@@ -1095,6 +1190,10 @@ namespace Serein.Workbench.Views
}
if (selectNodeControls.Count == 1)
{
+ var nodeConotrol = selectNodeControls[0];
+ // 选取了控件
+ flowNodeService.CurrentSelectNodeControl = nodeConotrol; // 更新选取节点显示
+ App.GetService().CurrentMethodDetailsInfo = nodeConotrol.ViewModel.NodeModel.MethodDetails.ToInfo();
// ChangeViewerObjOfNode(selectNodeControls[0]);
}
diff --git a/Workbench/Views/FlowWorkbenchView.xaml b/Workbench/Views/FlowWorkbenchView.xaml
index 24ed111..3948c03 100644
--- a/Workbench/Views/FlowWorkbenchView.xaml
+++ b/Workbench/Views/FlowWorkbenchView.xaml
@@ -14,9 +14,9 @@
-
+
-
+
@@ -31,16 +31,34 @@
-
-
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/Workbench/Views/ViewCanvasInfoView.xaml b/Workbench/Views/ViewCanvasInfoView.xaml
new file mode 100644
index 0000000..4171ad3
--- /dev/null
+++ b/Workbench/Views/ViewCanvasInfoView.xaml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Workbench/Views/ViewCanvasInfoView.xaml.cs b/Workbench/Views/ViewCanvasInfoView.xaml.cs
new file mode 100644
index 0000000..303f572
--- /dev/null
+++ b/Workbench/Views/ViewCanvasInfoView.xaml.cs
@@ -0,0 +1,51 @@
+using Serein.Library;
+using Serein.Library.Api;
+using Serein.Workbench.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Serein.Workbench.Views
+{
+ ///
+ /// CanvasNodeTreeView.xaml 的交互逻辑
+ ///
+ public partial class ViewCanvasInfoView : UserControl
+ {
+ private readonly ViewCanvasInfoViewModel ViewModel;
+ private readonly ViewNodeInfoViewModel NodeInfoViewModel;
+ public ViewCanvasInfoView()
+ {
+ this.ViewModel = App.GetService();
+ this.NodeInfoViewModel = App.GetService();
+ this.DataContext = this.ViewModel;
+ InitializeComponent();
+ }
+
+ private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ if (sender is Grid grid && grid.DataContext is NodeModelBase nodeModel)
+ {
+ NodeInfoViewModel.ViewNodeModel = nodeModel;
+ App.GetService().NodeLocated(nodeModel.Guid);
+ }
+
+ // 定位节点
+ //if (e.ClickCount == 2)
+ //{
+ //}
+ }
+ }
+}
diff --git a/Workbench/Views/ViewNodeInfoView.xaml b/Workbench/Views/ViewNodeInfoView.xaml
new file mode 100644
index 0000000..c34731e
--- /dev/null
+++ b/Workbench/Views/ViewNodeInfoView.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Workbench/Views/CanvasInfoView.xaml.cs b/Workbench/Views/ViewNodeInfoView.xaml.cs
similarity index 64%
rename from Workbench/Views/CanvasInfoView.xaml.cs
rename to Workbench/Views/ViewNodeInfoView.xaml.cs
index 3bf02f0..9518706 100644
--- a/Workbench/Views/CanvasInfoView.xaml.cs
+++ b/Workbench/Views/ViewNodeInfoView.xaml.cs
@@ -17,15 +17,16 @@ using System.Windows.Shapes;
namespace Serein.Workbench.Views
{
///
- /// CanvasNodeTreeView.xaml 的交互逻辑
+ /// NodeInfoView.xaml 的交互逻辑
///
- public partial class CanvasInfoView : UserControl
+ public partial class ViewNodeInfoView : UserControl
{
- private readonly CanvasInfoViewModel ViewModel;
- public CanvasInfoView()
+ private readonly ViewNodeInfoViewModel ViewModel;
+ public ViewNodeInfoView()
{
- this.ViewModel = App.GetService();
- this.DataContext = this.ViewModel;
+
+ ViewModel = App.GetService().NodeInfoViewModel;
+ this.DataContext = ViewModel;
InitializeComponent();
}
}
diff --git a/Workbench/Views/ViewNodeMethodInfoView.xaml b/Workbench/Views/ViewNodeMethodInfoView.xaml
new file mode 100644
index 0000000..8fd5411
--- /dev/null
+++ b/Workbench/Views/ViewNodeMethodInfoView.xaml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Workbench/Views/ViewNodeMethodInfoView.xaml.cs b/Workbench/Views/ViewNodeMethodInfoView.xaml.cs
new file mode 100644
index 0000000..c64533b
--- /dev/null
+++ b/Workbench/Views/ViewNodeMethodInfoView.xaml.cs
@@ -0,0 +1,33 @@
+using Serein.Workbench.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Serein.Workbench.Views
+{
+ ///
+ /// NodeMethodInfoView.xaml 的交互逻辑
+ ///
+ public partial class ViewNodeMethodInfoView : UserControl
+ {
+ private readonly ViewNodeMethodInfoViewModel ViewModel;
+
+ public ViewNodeMethodInfoView()
+ {
+ ViewModel = App.GetService().ViewNodeMethodInfoViewModel;
+ this.DataContext = ViewModel;
+ InitializeComponent();
+ }
+ }
+}