2022-06-22 12:12:33 +00:00
本画板在WPF-Diagram-Designer的基础上进行的开发, 界面框架使用Fluent.Ribbon的框架。
先上源码地址: https://gitee.com/akwkevin/aistudio.-wpf.-diagram
2023-05-12 06:16:18 +00:00
## 写在前面
友情提示 很多朋友老问为什么编译不过去, 您需要安装对应的net版本, 或者修改工程的net版本, 如下图。
2023-05-12 06:16:50 +00:00

2022-06-22 12:12:33 +00:00
2023-07-02 04:22:57 +00:00
## 2023年7月2日更新内容(做一个Block编程画板)
先上一张效果动图,本次更新主要仿照Scratch, 目前仅完成拖拽部分, 逻辑部分后续完善。

### 本次扩展主要内容:
### 1.Block模块, 入口在文件新建下。

### 2.简易Block的使用:

### 3.仿Scratch的Block的使用( 完成图鉴, 准备编写逻辑) :

2023-05-20 09:28:02 +00:00
## 2023年5月17日更新内容(做一个画笔画板)
2023-05-20 09:26:20 +00:00
2023-05-20 09:29:35 +00:00

2023-05-20 09:26:20 +00:00
2023-05-20 09:29:35 +00:00
### 更新内容如下
- [1] 画笔实现
- [2] 封闭画笔实现
- [3] 钢笔实现
- [4] 文字画笔
- [5] 直线,矩形,椭圆
- [6] Path形状
- [7] 取色器
- [8] 三种画笔可选
2023-05-17 14:53:15 +00:00
2023-05-20 09:28:02 +00:00
### 画笔示例入口
2023-05-20 09:26:20 +00:00

2023-05-20 09:29:35 +00:00

2023-05-20 09:26:20 +00:00
2023-05-20 09:28:02 +00:00
### 画笔示例截图

2023-05-03 13:56:38 +00:00
## 2023年5月1号更新内容( 做一个可编程画板) :
2023-05-01 16:00:33 +00:00
2023-05-03 13:45:07 +00:00

2023-05-01 16:00:33 +00:00
2023-05-03 14:08:55 +00:00
### 1.简单使用, 自定义一个text模块的代码如下:
2023-05-01 16:00:33 +00:00
```
Code = @"using System;
namespace AIStudio.Wpf.CSharpScript
{
public class Writer
{
public string StringValue{ get; set;} = ""Welcome to AIStudio.Wpf.Diagram"";
public string Execute()
{
return StringValue;
}
}
}";
```
是不是很简单。
2023-05-03 14:08:55 +00:00
### 2.本次扩展的主要内容
2023-05-03 14:14:07 +00:00
2023-05-03 14:08:55 +00:00
【1】.可编程模块, 使用C#语言 。
2023-05-03 14:14:07 +00:00
2023-05-03 14:08:55 +00:00
【2】.控制台打印控件, 可以打印程序中的Console.WriteLine数据
2023-05-03 14:14:07 +00:00
2023-05-03 14:08:55 +00:00
【3】.为了便于大家使用, 写了一个Box工厂分配Box的数据流向效果图。
2023-05-01 16:00:33 +00:00
2023-05-03 14:08:55 +00:00
### 3.可编程模块的实现原理
2023-05-01 16:00:33 +00:00
使用Microsoft.CodeAnalysis.CSharp.Scripting对代码进行编译, 生成Assembly, 然后对Assembly反射获得对象, 对象内部固定有一个Execute方法, 每次扫描的时候执行即可。
1.编译使用的Using,必须添加引用集, 为了省事, 把整个程序的Reference都放入进行编译, 获得引用的核心代码如下:
```
var references = AppDomain.CurrentDomain.GetAssemblies().Where(p => !p.IsDynamic && !string.IsNullOrEmpty(p.Location)).Select(x => MetadataReference.CreateFromFile(x.Location)).ToList();
//Costura.Fody压缩后, 无Location, 读取资源文件中的reference
foreach (var assemblyEmbedded in AppDomain.CurrentDomain.GetAssemblies().Where(p => !p.IsDynamic && string.IsNullOrEmpty(p.Location)))
{
using (var stream = Assembly.GetEntryAssembly().GetManifestResourceStream($"costura.{assemblyEmbedded.GetName().Name.ToLowerInvariant()}.dll.compressed"))
{
if (stream != null)
{
using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress))
{
var memStream = new MemoryStream();
CopyTo(compressStream, memStream);
memStream.Position = 0;
references.Add(MetadataReference.CreateFromStream(memStream));
}
}
}
}
```
2.动态编译的代码的核心代码如下:
```
public static Assembly GenerateAssemblyFromCode(string code, out string message)
{
Assembly assembly = null;
message = "";
// 丛代码中转换表达式树
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
// 随机程序集名称
string assemblyName = Path.GetRandomFileName();
// 引用
// 创建编译对象
CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, References, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
// 将编译好的IL代码放入内存流
EmitResult result = compilation.Emit(ms);
// 编译失败,提示
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error).ToList();
foreach (Diagnostic diagnostic in failures)
{
message += $"{diagnostic.Id}: {diagnostic.GetMessage()}";
Console.WriteLine(message);
}
}
else
{
// 编译成功,从内存中加载编译好的程序集
ms.Seek(0, SeekOrigin.Begin);
assembly = Assembly.Load(ms.ToArray());
}
}
return assembly;
}
```
3.获得编译后的程序集,以及执行。
```
// 反射获取程序集中 的类
Type type = assembly.GetTypes().FirstOrDefault(p => p.FullName.StartsWith("AIStudio.Wpf")); //assembly.GetType("AIStudio.Wpf.CSharpScript.Write");
// 创建该类的实例
object obj = Activator.CreateInstance(type);
// 通过反射方式调用类中的方法。
var result = type.InvokeMember("Execute",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
obj,
new object[] { });
```
2023-05-03 14:08:55 +00:00
### 4.代码编辑模块的实现
2023-05-01 16:00:33 +00:00
选择AvalonEdit控件, 另外为了使用VS2019_Dark的黑色皮肤, 引用官方Demo中的HL和TextEditlib实现自定义换肤。
2023-05-01 16:04:01 +00:00
2023-05-03 13:50:29 +00:00

2023-05-01 16:04:01 +00:00
2023-05-01 16:00:33 +00:00
官方Demo的换肤写的超级复杂, 看不懂, 但是我们只要理解换肤的核心部分就是动态资源字典, 因此我简化下, 改进后的核心换肤代码如下:
```
public class TextEditorThemeHelper
{
static Dictionary<string, ResourceDictionary> ThemeDictionary = new Dictionary<string, ResourceDictionary>();
public static List<string> Themes = new List<string>() { "Dark", "Light", "TrueBlue", "VS2019_Dark" };
public static string CurrentTheme { get; set; }
static TextEditorThemeHelper()
{
var resource = new ResourceDictionary { Source = new Uri("/TextEditLib;component/Themes/LightBrushs.xaml", UriKind.RelativeOrAbsolute) };
ThemeDictionary.Add("Light", resource);
resource = new ResourceDictionary { Source = new Uri("/TextEditLib;component/Themes/DarkBrushs.xaml", UriKind.RelativeOrAbsolute) };
ThemeDictionary.Add("Dark", resource);
Application.Current.Resources.MergedDictionaries.Add(resource);
}
/// <summary>
/// 设置主题
/// </summary>
/// <param name="theme"></param>
public static void SetCurrentTheme(string theme)
{
OnAppThemeChanged(theme);//切换到VS2019_Dark
CurrentTheme = theme;
}
/// <summary>
/// Invoke this method to apply a change of theme to the content of the document
/// (eg: Adjust the highlighting colors when changing from "Dark" to "Light"
/// WITH current text document loaded.)
/// </summary>
internal static void OnAppThemeChanged(string theme)
{
ThemedHighlightingManager.Instance.SetCurrentTheme(theme);
if (ThemeDictionary.ContainsKey(theme))
{
foreach (var key in ThemeDictionary[theme].Keys)
{
ApplyToDynamicResource(key, ThemeDictionary[theme][key]);
}
}
// Does this highlighting definition have an associated highlighting theme?
else if (ThemedHighlightingManager.Instance.CurrentTheme.HlTheme != null)
{
// A highlighting theme with GlobalStyles?
// Apply these styles to the resource keys of the editor
foreach (var item in ThemedHighlightingManager.Instance.CurrentTheme.HlTheme.GlobalStyles)
{
switch (item.TypeName)
{
case "DefaultStyle":
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorBackground, item.backgroundcolor);
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorForeground, item.foregroundcolor);
break;
case "CurrentLineBackground":
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorCurrentLineBackgroundBrushKey, item.backgroundcolor);
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorCurrentLineBorderBrushKey, item.bordercolor);
break;
case "LineNumbersForeground":
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorLineNumbersForeground, item.foregroundcolor);
break;
case "Selection":
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorSelectionBrush, item.backgroundcolor);
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorSelectionBorder, item.bordercolor);
break;
case "Hyperlink":
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorLinkTextBackgroundBrush, item.backgroundcolor);
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorLinkTextForegroundBrush, item.foregroundcolor);
break;
case "NonPrintableCharacter":
ApplyToDynamicResource(TextEditLib.Themes.ResourceKeys.EditorNonPrintableCharacterBrush, item.foregroundcolor);
break;
default:
throw new System.ArgumentOutOfRangeException("GlobalStyle named '{0}' is not supported.", item.TypeName);
}
}
}
}
/// <summary>
/// Re-define an existing <seealso cref="SolidColorBrush"/> and backup the originial color
/// as it was before the application of the custom coloring.
/// </summary>
/// <param name="key"></param>
/// <param name="newColor"></param>
private static void ApplyToDynamicResource(ComponentResourceKey key, Color? newColor)
{
if (Application.Current.Resources[key] == null || newColor == null)
return;
// Re-coloring works with SolidColorBrushs linked as DynamicResource
if (Application.Current.Resources[key] is SolidColorBrush)
{
//backupDynResources.Add(resourceName);
var newColorBrush = new SolidColorBrush((Color)newColor);
newColorBrush.Freeze();
Application.Current.Resources[key] = newColorBrush;
}
}
private static void ApplyToDynamicResource(object key, object newValue)
{
if (Application.Current.Resources[key] == null || newValue == null)
return;
Application.Current.Resources[key] = newValue;
}
}
```
使用方法:
TextEditorThemeHelper.SetCurrentTheme("VS2019_Dark");
2023-05-03 14:14:07 +00:00
2023-05-01 16:00:33 +00:00
或者
TextEditorThemeHelper.SetCurrentTheme("TrueBlue");
2023-05-03 14:14:07 +00:00
2023-05-01 16:00:33 +00:00
或者
TextEditorThemeHelper.SetCurrentTheme("Dark");
2023-05-03 14:14:07 +00:00
2023-05-01 16:00:33 +00:00
或者
TextEditorThemeHelper.SetCurrentTheme("Light");
2023-05-03 14:14:07 +00:00
2023-05-01 16:00:33 +00:00
是不是超级简单。
2023-05-03 14:14:07 +00:00
2023-05-03 14:08:55 +00:00
### 5.代码编辑模块的编译与测试。
2023-05-01 16:00:33 +00:00
2023-05-03 13:50:29 +00:00

2023-05-01 16:04:01 +00:00
2023-05-03 13:50:29 +00:00

2023-05-01 16:04:01 +00:00
2023-05-03 14:08:55 +00:00
### 6.WPF打印控制台数据
2023-05-01 16:00:33 +00:00
```
控制台打印方法支持切换运行输出方法Console.SetOut, 核心代码如下:
public class ConsoleWriter : TextWriter
{
private readonly Action<string> _Write;
private readonly Action<string> _WriteLine;
private readonly Action<string, string, string, int> _WriteCallerInfo;
public ConsoleWriter()
{
}
/// <summary>
/// Console 输出重定向
/// </summary>
/// <param name="write">日志方法委托(针对于 Write) </param>
/// <param name="writeLine">日志方法委托(针对于 WriteLine) </param>
public ConsoleWriter(Action<string> write, Action<string> writeLine, Action<string, string, string, int> writeCallerInfo)
{
_Write = write;
_WriteLine = writeLine?? write;
_WriteCallerInfo = writeCallerInfo;
}
/// <summary>
/// Console 输出重定向
/// </summary>
/// <param name="write">日志方法委托(针对于 Write) </param>
/// <param name="writeLine">日志方法委托(针对于 WriteLine) </param>
public ConsoleWriter(Action<string> write, Action<string> writeLine)
{
_Write = write;
_WriteLine = writeLine;
}
/// <summary>
/// Console 输出重定向
/// </summary>
/// <param name="write">日志方法委托</param>
public ConsoleWriter(Action<string> write)
{
_Write = write;
_WriteLine = write;
}
/// <summary>
/// Console 输出重定向(带调用方信息)
/// </summary>
/// <param name="write">日志方法委托(后三个参数为 CallerFilePath、CallerMemberName、CallerLineNumber) </param>
public ConsoleWriter(Action<string, string, string, int> write)
{
_WriteCallerInfo = write;
}
/// <summary>
/// 使用 UTF-16 避免不必要的编码转换
/// </summary>
public override Encoding Encoding => Encoding.Unicode;
/// <summary>
/// 最低限度需要重写的方法
/// </summary>
/// <param name="value">消息</param>
public override void Write(string value)
{
if (_WriteCallerInfo != null)
{
WriteWithCallerInfo(value);
return;
}
_Write(value);
}
/// <summary>
/// 为提高效率直接处理一行的输出
/// </summary>
/// <param name="value">消息</param>
public override void WriteLine(string value)
{
if (_WriteCallerInfo != null)
{
WriteWithCallerInfo(value);
return;
}
_WriteLine(value);
}
/// <summary>
/// 带调用方信息进行写消息
/// </summary>
/// <param name="value">消息</param>
private void WriteWithCallerInfo(string value)
{
//3、System.Console.WriteLine -> 2、System.IO.TextWriter + SyncTextWriter.WriteLine -> 1、DotNet.Utilities.ConsoleHelper.ConsoleWriter.WriteLine -> 0、DotNet.Utilities.ConsoleHelper.ConsoleWriter.WriteWithCallerInfo
var callInfo = ClassHelper.GetMethodInfo(4);
_WriteCallerInfo(value, callInfo?.FileName, callInfo?.MethodName, callInfo?.LineNumber ?? 0);
}
public override void Close()
{
var standardOutput = new StreamWriter(Console.OpenStandardOutput());
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
base.Close();
}
}
```
2023-05-03 14:14:53 +00:00
使用:
ConsoleWriter ConsoleWriter = new ConsoleWriter(_write, _writeLine);
Console.SetOut(ConsoleWriter);
2023-05-01 16:00:33 +00:00
2023-05-03 14:08:55 +00:00
### 7.动态编译模块的输入输出自动生成。
2023-05-01 16:00:33 +00:00
1.输入输出模块: public string Value{ get; set;}
2.输入模块: public string Value{private get; set;}
3.输出模块: public string Value{get;private set;}
4.与外部交互模块: private string Value{ get; set;} ,必须同名同属性。
核心代码如下:
```
public static Dictionary<string, List<PropertyInfo>> GetPropertyInfo(Type type)
{
Dictionary<string, List<PropertyInfo>> puts = new Dictionary<string, List<PropertyInfo>>()
{
{"Input", new List<PropertyInfo>() },
{"Output", new List<PropertyInfo>() },
{"Input_Output", new List<PropertyInfo>() },
{"Inner", new List<PropertyInfo>() }
};
try
{
foreach (System.Reflection.PropertyInfo info in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (info.CanRead && info.CanWrite)
{
if (info.SetMethod.IsPublic && info.GetMethod.IsPublic)
{
puts["Input_Output"].Add(info);
}
else if (info.SetMethod.IsPublic)
{
puts["Input"].Add(info);
}
else if (info.GetMethod.IsPublic)
{
puts["Output"].Add(info);
}
}
else if (info.CanRead)
{
if (info.GetMethod.IsPublic)
{
puts["Output"].Add(info);
}
}
}
foreach (System.Reflection.PropertyInfo info in type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance))
{
if (info.CanRead)
{
puts["Inner"].Add(info);
}
}
}
catch (Exception ex)
{
}
return puts;
}
```
2023-05-03 14:08:55 +00:00
### 8.最后介绍一下Demo的实现。
2023-05-01 16:00:33 +00:00
1#.Int整数模块, 界面定义一个TextBox绑定Int模块的输入管脚。
2#.Box产生模块, 如果内部数组为空, 那么按照输入管脚的数量初始化一个容量为输入整数数量的数组( 随机颜色与形状) , 然后把数据放到输出管脚, 当数据被取走后, 下一个数据再次放到输出管脚。
3#.Bool模块, 为false的时候按照颜色进行分配, 为true的时候按照形状进行分配。
4#.Box分配模块, 当输入管脚为空的时候, 2#模块的输出可以移动到4 #的输入管脚 , 移动时间为1s, 移动完成后, 清除2#模块的输出 。同时把数据按照颜色或者形状分配到输出,同时把输入管脚清除。
按照颜色分配时:
( 1.如果颜色为红色, 那么输出到1号
( 2.如果颜色为橙色, 那么输出到2号
( 3.如果颜色为黄色, 那么输出到3号
( 4.如果颜色为绿色, 那么输出到4号
( 5.如果颜色为青色, 那么输出到5号
( 6.如果颜色为蓝色, 那么输出到6号
( 7.如果颜色为紫色, 那么输出到7号
按照形状分配时:
( 1.如果形状为圆形, 那么输出到1号
( 2.如果形状为三角形, 那么输出到2号
( 3.如果形状为方形, 那么输出到3号
( 4.如果形状为菱形, 那么输出到4号
( 5.如果形状为梯形, 那么输出到5号
( 6.如果形状为五角星, 那么输出到6号
( 7.如果形状为六边形, 那么输出到7号
6#.有两个红色|圆形收集器( 7#, 8#),按两个容器中的数量比较反馈,均匀分配到这两个收集器中。
9#, 10#, 11#, 12#, 13#, 14#按照管脚取走数据即可 。
2023-05-03 13:56:38 +00:00
## 2023年4月5号更新内容( 本次更新主要仿照百度脑图) :
2023-05-03 14:08:55 +00:00
### 1.思维导图、目录组织图、鱼骨头图、逻辑结构图、组织结构图,入口在文件新建下。
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
### 2.思维导图工具栏(只有思维导图模式下可见)
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.1插入链接
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.2插入图片
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.3插入备注
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.4插入优先级
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.5插入进度
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.6切换类型
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00




2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.7切换主题
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00






2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
#### 2.8还有展开节点,全选,居中,适应窗体大小等功能,不在介绍。
2023-04-05 01:15:37 +00:00
2023-05-03 14:08:55 +00:00
### 3 添加搜索功能(不仅仅思维导图可以使用)
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:15:37 +00:00
2023-05-03 14:11:15 +00:00
### 4 MindEditor: 最后为了方便大家使用, 我封装了一个思维脑图的控件MindEditor, 可以直接绑定json格式的数据, 数据改变, 可以直接加载应用。( 见[AIStudio.Wpf.DiagramDesigner.Demo](https://gitee.com/akwkevin/aistudio.-wpf.-diagram/tree/master/Demos/AIStudio.Wpf.DiagramDesigner.Demo))
2023-04-05 01:14:51 +00:00
2023-05-03 13:50:29 +00:00

2023-04-05 01:12:22 +00:00
2023-05-03 13:56:38 +00:00
## 2023年2月5号更新内容:
2023-02-05 12:27:44 +00:00
本次更新主要参照了一个Blazor的Diagram的画线算法, 链接地址:[https://github.com/Blazor-Diagrams/Blazor.Diagrams ](https://github.com/Blazor-Diagrams/Blazor.Diagrams ),感谢作者。
### 1.连线改进, 新增连线算法, 目前共4种连线: Smooth( 曲线) , Straight( 直线) , Boundary( 网格边界连接模式) , Corner( 折线)
### 2.序列化改进, xml与json序列化, 新增自定义元素后, 无需更改根元素, 只需要在新增的元素上添加序列化的对象即可, 扩展性更灵活了。
### 3.箭头改进, 箭头按照连线的实际角度显示( 即0-360度) , 还支持自定义的箭头path。
### 4.新增快捷键自定义扩展,用户可根据自己的习惯定义快捷键。
2023-05-03 14:11:15 +00:00
### 5.FlowchartEditor: 封装了一个标准的工作流控件FlowchartEditor, 具体使用可以参照开源权限管理框架种的用法: [https://gitee.com/akwkevin/aistudio.-wpf.-aclient](https://gitee.com/akwkevin/aistudio.-wpf.-aclient)
2023-02-09 04:06:25 +00:00
2023-05-03 13:50:29 +00:00
nuget地址: 
2023-02-09 04:06:25 +00:00
2023-02-05 12:27:44 +00:00
### 6.连接上添加动画:路径动画效果和线条流动效果。
### 7.改变结构,使用户更容易自定义自己的样式,覆盖系统默认样式。
### 8.从Blazor.Diagrams种引入PortlessLinks( 直接连接两个node, 不需要port) , 自动连接节点Snapping, 按距离最近连接ReconnectLinksToClosestPorts
2023-02-05 14:49:04 +00:00
### 9.新增Demo示例, 帮助用户快速上手, 见底部2023年2月5号更新附加说明。
2023-02-05 12:27:44 +00:00
2023-05-03 13:56:38 +00:00
## 2023年之前发布内容:
2022-06-22 12:12:33 +00:00
界面图:
本画板在WPF-Diagram-Designer进行的开发, 界面框架使用Fluent.Ribbon的框架。
界面图:

2023-05-03 14:08:55 +00:00
### 1.支持字体样式,字体颜色,字体阴影,对齐方向,行间距。
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 2.支持复制粘贴剪贴,格式化,撤销重做。
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 3.支持形状绘制。
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 4.连接线
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 5.位置,组合,对齐
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 6.元素翻转,旋转。
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 7.填充颜色,支持线性渐变色,径向渐变色等
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 8.支持箭头样式
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 9.锁定与解锁
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 10.快速样式
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 11.支持矢量文本,二维码
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 12.支持插入图片, 视频, SVG
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 13.支持画板大小,方向,标尺,网格是否显示,画板背景色
2022-06-22 12:12:33 +00:00
2023-05-03 14:08:55 +00:00
### 14.支持流程图(在文件新建下-基本绘图-流程图)
2022-06-22 12:12:33 +00:00


2023-05-03 14:08:55 +00:00
### 15支持逻辑图( 在文件新建下-基本绘图-逻辑图)
2022-06-22 12:12:33 +00:00

2023-05-03 14:08:55 +00:00
### 16支持SFC顺序控制图( 在文件新建下-基本绘图-顺序控制图)
2022-06-22 12:12:33 +00:00
.png")
2023-05-03 14:08:55 +00:00
### 示例项目说明([AIStudio.Wpf.DiagramDesigner.Demo](https://gitee.com/akwkevin/aistudio.-wpf.-diagram/tree/master/Demos/AIStudio.Wpf.DiagramDesigner.Demo))目录如下:
2023-02-05 12:27:44 +00:00
2023-05-03 14:08:55 +00:00
#### 1 Simple 简单示例
2023-02-05 12:43:10 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 2 Locked 锁定节点
#### 3 Events 事件(暂未完成,敬请期待)
#### 4 DynamicInsertions 动态插入(暂未完成,敬请期待)
#### 5 Performance 性能( 100个节点生成)
#### 6 Zoom 放大缩小
#### 7 SnapToGrid 对齐到网格
2023-02-05 12:43:10 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 8 DragAndDrop 拖拽
2023-02-05 12:43:10 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 9 Nodes 节点示例
##### 9.1 Svg svg样式
2023-02-05 12:43:10 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 9.2 CustomDefinedNode 自定义节点
2023-02-05 12:43:10 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 9.3 PortlessLinks 无Port的node连接
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 9.4 GradientNode 渐变色node
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 9.5 Rotate 旋转node( 连接线还需要优化, 还算连接在旋转之前的位置上)
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 10 Links 连线示例
##### 10.1 Snapping 连接线靠近节点自动连接
##### 10.2 Labels 连接线上的文字(支持多处)
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 10.3 Vertices 连接线上的中间节点
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 10.4 Markers 箭头,支持自定义
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 10.5 Routers 连线模式
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 10.6 PathGenerators 连线算法
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 11 Ports 连接点示例
##### 11.1 ColoredPort 彩色连接点,相同颜色的连接点才能连接
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 11.2 InnerPort 内部连接点
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 12 Groups 分组示例
##### 12.1 Group 分组
##### 12.2 CustomDefinedGroup 自定义分组
##### 12.3 CustomShortcutGroup 自定义分组快捷键
#### 13 Texts 文本节点示例
##### 13.1 Text 文本
##### 13.2 Alignment 对齐方式
##### 13.3 FontSize 字体大小
##### 13.4 ColorText 彩色字体
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 13.5 OutlineText 轮廓文本
#### 14 Customization 自定义
##### 14.1 CustomNode 覆盖默认节点样式
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 14.2 CustomLink 设置线条连接样式
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 14.3 CustomPort 覆盖默认连接点样式
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
##### 14.4 CustomGroup 覆盖默认分组样式
2023-02-05 13:35:24 +00:00
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 15 Algorithms 算法
##### 14.6 ReconnectLinksToClosestPorts 重新计算,按最近的连接点连接。
#### 15 Animations
##### 15.1 PathAnimation 动画路径
2023-05-03 13:54:23 +00:00

2023-05-03 14:08:55 +00:00
##### 15.2 LineAnimation 线条流动动画
2023-05-03 13:50:29 +00:00

2023-05-03 14:08:55 +00:00
#### 16 Editor
##### 16.1 FlowchartEditor 工作流封装控件
2023-02-12 07:25:35 +00:00
采用兼容主流的diagram的序列化格式
2023-05-03 13:50:29 +00:00

2023-02-12 07:26:25 +00:00
2023-02-12 07:25:35 +00:00
`{"Nodes":[{"Kind":1,"UserIds":null,"RoleIds":null,"ActType":null,"Id":"e0f2c29c-2c89-4c0c-857e-35eb0b121d7e","ParentId":null,"Name":null,"Color":"#1890ff ","Label":"开始","Width":100.0,"Height":80.0,"X":12.5,"Y":147.5,"Type":"FlowchartNode","ZIndex":0,"PortAlignmentList":["Top","Bottom","Left","Right","Top","Bottom","Left","Right"]},{"Kind":3,"UserIds":[],"RoleIds":[],"ActType":null,"Id":"716f64ec-bcdb-438c-9748-9546abf990cc","ParentId":null,"Name":null,"Color":"#1890ff ","Label":"节点1","Width":100.0,"Height":80.0,"X":137.5,"Y":147.5,"Type":"FlowchartNode","ZIndex":2,"PortAlignmentList":["Top","Bottom","Left","Right","Top","Bottom","Left","Right"]},{"Kind":4,"UserIds":null,"RoleIds":null,"ActType":null,"Id":"3cd6c332-6b5b-44ef-96c4-c7aef66fd5dd","ParentId":null,"Name":null,"Color":"#1890ff ","Label":"条件节点","Width":100.0,"Height":80.0,"X":262.5,"Y":147.5,"Type":"FlowchartNode","ZIndex":3,"PortAlignmentList":["Top","Bottom","Left","Right","Top","Bottom","Left","Right"]},{"Kind":3,"UserIds":[],"RoleIds":[],"ActType":null,"Id":"7d953234-ddff-4701-a52a-bf6460ffa7b9","ParentId":null,"Name":null,"Color":"#1890ff ","Label":"节点2","Width":100.0,"Height":80.0,"X":387.5,"Y":22.5,"Type":"FlowchartNode","ZIndex":6,"PortAlignmentList":["Top","Bottom","Left","Right","Top","Bottom","Left","Right"]},{"Kind":3,"UserIds":[],"RoleIds":[],"ActType":null,"Id":"7dfd4102-2751-42c7-a386-adcfcca27ede","ParentId":null,"Name":null,"Color":"#1890ff ","Label":"节点3","Width":100.0,"Height":80.0,"X":387.5,"Y":272.5,"Type":"FlowchartNode","ZIndex":7,"PortAlignmentList":["Top","Bottom","Left","Right","Top","Bottom","Left","Right"]},{"Kind":2,"UserIds":null,"RoleIds":null,"ActType":null,"Id":"ad57e53f-8860-4212-9afb-f67e14eecbc8","ParentId":null,"Name":null,"Color":"#1890ff ","Label":"结束","Width":100.0,"Height":80.0,"X":512.5,"Y":147.5,"Type":"FlowchartNode","ZIndex":10,"PortAlignmentList":["Top","Bottom","Left","Right","Top","Bottom","Left","Right"]}],"Links":[{"Id":"65f6432f-2084-462d-93d8-a6b3ff889182","Color":"#FF808080 ","SelectedColor":"#FF000000 ","Width":2.0,"Label":null,"SourceId":"e0f2c29c-2c89-4c0c-857e-35eb0b121d7e","TargetId":"716f64ec-bcdb-438c-9748-9546abf990cc","SourcePortAlignment":"Right","TargetPortAlignment":"Left","Type":"DiagramLink","Router":null,"PathGenerator":null,"SourceMarkerPath":null,"SourceMarkerWidth":null,"TargetMarkerPath":null,"TargetMarkerWidth":null},{"Id":"7d1dcf2d-ee69-4c24-84ff-3a99b6555692","Color":"#FF808080 ","SelectedColor":"#FF000000 ","Width":2.0,"Label":null,"SourceId":"716f64ec-bcdb-438c-9748-9546abf990cc","TargetId":"3cd6c332-6b5b-44ef-96c4-c7aef66fd5dd","SourcePortAlignment":"Right","TargetPortAlignment":"Left","Type":"DiagramLink","Router":null,"PathGenerator":null,"SourceMarkerPath":null,"SourceMarkerWidth":null,"TargetMarkerPath":null,"TargetMarkerWidth":null},{"Id":"cd18c02f-0cdb-4eb5-9793-b9db87eeea09","Color":"#FF808080 ","SelectedColor":"#FF000000 ","Width":2.0,"Label":"条件1","SourceId":"3cd6c332-6b5b-44ef-96c4-c7aef66fd5dd","TargetId":"7d953234-ddff-4701-a52a-bf6460ffa7b9","SourcePortAlignment":"Top","TargetPortAlignment":"Left","Type":"DiagramLink","Router":null,"PathGenerator":null,"SourceMarkerPath":null,"SourceMarkerWidth":null,"TargetMarkerPath":null,"TargetMarkerWidth":null},{"Id":"69bbb083-8eb4-403b-937a-b0f0d3c80eb0","Color":"#FF808080 ","SelectedColor":"#FF000000 ","Width":2.0,"Label":"条件2","SourceId":"3cd6c332-6b5b-44ef-96c4-c7aef66fd5dd","TargetId":"7dfd4102-2751-42c7-a386-adcfcca27ede","SourcePortAlignment":"Bottom","TargetPortAlignment":"Left","Type":"DiagramLink","Router":null,"PathGenerator":null,"SourceMarkerPath":null,"SourceMarkerWidth":null,"TargetMarkerPath":null,"TargetMarkerWidth":null},{"Id":"d640c547-5ba8-428c-8d65-74874b1d28bd","Color":"#FF808080 ","SelectedColor":"#FF000000 ","Width":2.0,"Label":null,"SourceId":"7d953234-ddff-4701-a52a-bf6460ffa7b9","TargetId":"ad57e53f-8860-4212-9afb-f67e14eecbc8","SourcePortAlignment":"Right","TargetPortAlignment":"Top","Type":"DiagramLink","Router":null,"PathGenerator":null,"SourceMarkerPath":null,"SourceMarkerWidth":nul
2023-02-05 12:27:44 +00:00
近期会持续更新,欢迎大家光临。
2023-05-03 14:08:55 +00:00
##### 最后上一个动画流程图。
2023-05-03 13:50:29 +00:00

2023-02-05 13:39:16 +00:00
2023-05-03 14:01:21 +00:00
## 特别说明
2023-05-03 14:11:15 +00:00
### 博客园文章地址 [https://www.cnblogs.com/akwkevin/p/15047453.html](https://www.cnblogs.com/akwkevin/p/15047453.html)
2023-05-03 14:01:21 +00:00
2023-05-03 14:11:15 +00:00
### 用Wpf做一个Diagram画板( 续2) ( 包含封装一个控件FlowchartEditor) : [https://www.cnblogs.com/akwkevin/p/17093865.html](https://www.cnblogs.com/akwkevin/p/17093865.html)
2023-05-03 14:01:21 +00:00
2023-05-03 14:11:15 +00:00
### 用Wpf做一个思维导图( 续3-Diagram画板) [https://www.cnblogs.com/akwkevin/p/17288814.html](https://www.cnblogs.com/akwkevin/p/17288814.html)
2023-02-05 13:39:16 +00:00
2023-05-03 14:11:15 +00:00
### 用Wpf做一个可编程画板( 续4-Diagram画板) [https://www.cnblogs.com/akwkevin/p/17367212.html](https://www.cnblogs.com/akwkevin/p/17367212.html)
2023-02-05 13:39:16 +00:00
2023-05-20 09:44:54 +00:00
### 用Wpf做一个画笔画板( 续5-Diagram画板) [https://www.cnblogs.com/akwkevin/p/17417546.html](https://www.cnblogs.com/akwkevin/p/17417546.html)
2023-07-08 07:49:50 +00:00
## 捐助 如果您觉得我们的开源软件对你有所帮助,请扫下方二维码打赏我们一杯咖啡,开源不易,感谢您的支持。(可以联系我,在下面添加特别鸣谢,谢谢。)
2023-06-29 00:44:31 +00:00
2023-06-29 01:06:50 +00:00
<img src="Images/90d797c820ea33386617d32c148e1a9.jpg" width=30% >
2023-06-29 00:44:31 +00:00
2023-11-29 13:52:18 +00:00

2023-06-29 00:45:15 +00:00
2023-08-25 08:46:32 +00:00
## 捐赠列表:

2023-08-25 08:46:01 +00:00
2023-11-29 13:50:56 +00:00

2023-02-05 13:39:16 +00:00
相关链接地址:
Fluent.Ribbon: https://github.com/fluentribbon/Fluent.Ribbon
WPF-Diagram-Designer:https://github.com/LinRaise/WPF-Diagram-Designer
2023-10-28 09:37:38 +00:00
个人QQ:80267720,
2023-02-05 13:39:16 +00:00
2023-11-03 07:46:21 +00:00
QQ技术交流群1:51286643(已满), QQ技术交流群2:51280970( 如果您还喜欢, 帮忙点个星, 谢谢)
2023-02-05 13:39:16 +00:00
2023-08-25 08:46:01 +00:00
特别感谢: https://dotnet9.com/ 的站长: dotnet9。
2023-02-05 13:39:16 +00:00
有想加入开发的朋友可以联系我。