Nodify学习 三:连接器
前置
连接概述
连接是由两个点之间创建的。Source和Target依赖属性是Point类型,通常绑定到连接器的Anchor点。
基本连接
库中所有连接的基类是BaseConnection,它派生自Shape。在创建自定义连接时,可以不受任何限值地从BaseConnection派生。
它公开了两个命令及其对应的事件:
DisconnectCommand及DisconnectEvent- 当按住ALT点击连接时触发SplitCommand及SplitEvent- 当双击连接时触发
Nodify 控件支持 Input 和 Output 连接器,您可以通过重写 InputConnectorTemplate 和 OutputConnectorTemplate 的默认模板来自定义这些连接器
Direction 的连接可以有两个值:
Forward


Backward


和 SourceOffset 与 TargetOffset 锚点一起工作 OffsetMode ,并将与锚点保持距离:
连接也有一个 Spacing ,它将使连接在距 Source 和 Target 点一定距离处断开角度:
- With spacing: 带间距:

- Without spacing: 无间距:

设置为 ArrowSize “0,0”将删除箭头。
连接样式
Nodify 自带3个连接器样式
Line connection 直线连接
Circuit connection 电路连接
Connection 贝塞尔曲线连接
Line connection 直线连接
从 Source 到 Target 的直线。

Circuit connection 电路连接
具有 Angle 依赖项属性,用于控制其中断位置。角度以度为单位。

Connection 贝塞尔曲线连接
和 Target 之间的 Source 贝塞尔曲线。

操作
我们先创建一个NotifyPropertyBase类 作为消息通知的基类
public class NotifyPropertyBase : INotifyPropertyChanged
{ public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged([CallerMemberName] string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
} public void Set<T>(ref T field, T value, Action action = null, [CallerMemberName] string propName = "")
{
if (EqualityComparer<T>.Default.Equals(field, value))
return; field = value;
RaisePropertyChanged(propName);
action?.Invoke();
}
}
然后我们创建连接器类ConnectionViewModel 管理连接源和目标源
public class ConnectionViewModel
{
public ConnectionViewModel(ConnectorViewModel source, ConnectorViewModel target)
{
Source = source;
Target = target; Source.IsConnected = true;
Target.IsConnected = true;
} public ConnectorViewModel Source { get; }
public ConnectorViewModel Target { get; }
}
在EditorViewModel 类添加
public ObservableCollection<ConnectionViewModel> Connections { get; } = new ObservableCollection<ConnectionViewModel>();
调整ConnectorViewModel的属性
public class ConnectorViewModel: NotifyPropertyBase
{
public string Title { get; set; } private Point _anchor;
public Point Anchor
{
get => _anchor;
set => Set(ref _anchor, value);
} private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => Set(ref _isConnected, value);
}
}
在编辑器添加连接器样式
<nodify:NodifyEditor
x:Name="Editor"
Background="{StaticResource GridDrawingBrush}"
Connections="{Binding Connections}"
ItemsSource="{Binding Nodes}">
<nodify:NodifyEditor.DataContext>
<vm:EditorViewModel />
</nodify:NodifyEditor.DataContext>
<nodify:NodifyEditor.ItemTemplate>
<DataTemplate DataType="{x:Type mod:NodeViewModel}">
<nodify:Node
Header="{Binding Title}"
Input="{Binding Input}"
Output="{Binding Output}">
<nodify:Node.InputConnectorTemplate>
<DataTemplate DataType="{x:Type mod:ConnectorViewModel}">
<nodify:NodeInput
Anchor="{Binding Anchor, Mode=OneWayToSource}"
Header="{Binding Title}"
IsConnected="{Binding IsConnected}" />
</DataTemplate>
</nodify:Node.InputConnectorTemplate> <nodify:Node.OutputConnectorTemplate>
<DataTemplate DataType="{x:Type mod:ConnectorViewModel}">
<nodify:NodeOutput
Anchor="{Binding Anchor, Mode=OneWayToSource}"
Header="{Binding Title}"
IsConnected="{Binding IsConnected}" />
</DataTemplate>
</nodify:Node.OutputConnectorTemplate>
</nodify:Node>
</DataTemplate>
</nodify:NodifyEditor.ItemTemplate> <nodify:NodifyEditor.ConnectionTemplate>
<DataTemplate DataType="{x:Type mod:ConnectionViewModel}">
<nodify:Connection
Source="{Binding Source.Anchor}"
SourceOffsetMode="Rectangle"
Target="{Binding Target.Anchor}"
TargetOffsetMode="Rectangle" />
</DataTemplate>
</nodify:NodifyEditor.ConnectionTemplate>
</nodify:NodifyEditor>
然后添加一个新的节点看看 连接效果 这里我用了的
Connection连接样式
public class EditorViewModel
{
public ObservableCollection<NodeViewModel> Nodes { get; } = new ObservableCollection<NodeViewModel>();
public ObservableCollection<ConnectionViewModel> Connections { get; } = new ObservableCollection<ConnectionViewModel>();
public EditorViewModel()
{
var welcome = new NodeViewModel
{
Title = "我的第一个节点",
Input = new ObservableCollection<ConnectorViewModel>
{
new ConnectorViewModel
{
Title = "输入"
}
},
Output = new ObservableCollection<ConnectorViewModel>
{
new ConnectorViewModel
{
Title = "输出"
}
}
}; var nodify = new NodeViewModel
{
Title = "To Nodify",
Input = new ObservableCollection<ConnectorViewModel>
{
new ConnectorViewModel
{
Title = "In"
}
}
};
Nodes.Add(welcome);
Nodes.Add(nodify); Connections.Add(new ConnectionViewModel(welcome.Output[0], nodify.Input[0])); }
}

源码
github:zt199510/NodifySamples (github.com)
Nodify学习 三:连接器的更多相关文章
- HTTP学习三:HTTPS
HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...
- TweenMax动画库学习(三)
目录 TweenMax动画库学习(一) TweenMax动画库学习(二) TweenMax动画库学习(三) ...
- Struts2框架学习(三) 数据处理
Struts2框架学习(三) 数据处理 Struts2框架框架使用OGNL语言和值栈技术实现数据的流转处理. 值栈就相当于一个容器,用来存放数据,而OGNL是一种快速查询数据的语言. 值栈:Value ...
- 4.机器学习——统计学习三要素与最大似然估计、最大后验概率估计及L1、L2正则化
1.前言 之前我一直对于“最大似然估计”犯迷糊,今天在看了陶轻松.忆臻.nebulaf91等人的博客以及李航老师的<统计学习方法>后,豁然开朗,于是在此记下一些心得体会. “最大似然估计” ...
- DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件
DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件 本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...
- [ZZ] 深度学习三巨头之一来清华演讲了,你只需要知道这7点
深度学习三巨头之一来清华演讲了,你只需要知道这7点 http://wemedia.ifeng.com/10939074/wemedia.shtml Yann LeCun还提到了一项FAIR开发的,用于 ...
- SVG 学习<三>渐变
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
- Android JNI学习(三)——Java与Native相互调用
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- day91 DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件
DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件 本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...
- Django基础学习三_路由系统
今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...
随机推荐
- 功能齐全的 WPF 自定义控件资源库(收藏版)
前言 推荐一款界面美观.功能齐全的 WPF 自定义控件资源库.这款资源库通过封装一系列常用的控件,简化开发流程,加快项目交付速度. 控件介绍 资源库封装了一些常用的控件,将其整合到一个自定义的控件库中 ...
- win10中Docker安装、构建镜像、创建容器、Vscode连接实例
Docker方便一键构建项目所需的运行环境:首先构建镜像(Image).然后镜像实例化成为容器(Container),构成项目的运行环境.最后Vscode连接容器,方便我们在本地进行开发.下面以一个简 ...
- Rework:每个程序员都应该读的一本书
来源: 萌萌的博客 每一个程序员都有改变世界的梦想,他们不甘平凡,他们想要与众不同,他们想要创立世界上最酷的公司,那具体该如何做呢?风靡全球的<Rework>将告诉你答案. 37signa ...
- JAXP(Java API for XML Parsing)
JAXP(Java API for XML Parsing) 过去几年中,XML分折已经被标准为两个不同的处理模型:SAX(Simple API for XML)以及DOM(Document O ...
- JS之Class类
转载:https://juejin.cn/post/7098891689955164168 ECMAScript 6 提供了更接近传统语言的写法,新引入的class关键字具有正式定义类的能力.类(cl ...
- Codeforces Round 890 (Div. 2)
Tales of a Sort 题解 找到最大的能够产生逆序对的数即可 暴力\(O(n^2)\)枚举即可 const int N = 2e5 + 10, M = 4e5 + 10; int n; in ...
- 震惊!推荐一款AI驱动的自动化测试神器:TestCraft
在当今快速迭代的软件开发环境中,自动化测试已经成为确保软件质量的重要一环.然而,传统的手动录制和编写测试脚本的方式不仅耗时耗力,还难以跟上敏捷开发的节奏. 本文将为大家介绍一款基于AI技术的自动化测试 ...
- SpringCloudStream极简教程
简介 Spring Cloud Stream 是一个轻量级消息驱动微服务框架,旨在简化与消息中间件(如 Kafka.RabbitMQ 等)的集成,支持消息的发布和订阅模式.它提供了一种基于 Sprin ...
- DASCTF X CBCTF 2023 Misc Justlisten WP
DASCTF X CBCTF 2023 Misc Justlisten WP 又是一道很抽象的misc题 首先附件给了一个汉信码,扫码得到: 提示我们使用oursecret: password为0ur ...
- 推荐一款轻量级且强大的 Elasticsearch GUI : elasticvue
推荐一款轻量级且强大的 Elasticsearch GUI : elasticvue 很多同学都是用过 Elasticsearch 的 GUI 工具 Kibana ,但 Kibana 相对比较重,这篇 ...