前置

连接概述

连接是由两个点之间创建的。SourceTarget依赖属性是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学习 三:连接器的更多相关文章

  1. HTTP学习三:HTTPS

    HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...

  2. TweenMax动画库学习(三)

    目录               TweenMax动画库学习(一)            TweenMax动画库学习(二)            TweenMax动画库学习(三)           ...

  3. Struts2框架学习(三) 数据处理

    Struts2框架学习(三) 数据处理 Struts2框架框架使用OGNL语言和值栈技术实现数据的流转处理. 值栈就相当于一个容器,用来存放数据,而OGNL是一种快速查询数据的语言. 值栈:Value ...

  4. 4.机器学习——统计学习三要素与最大似然估计、最大后验概率估计及L1、L2正则化

    1.前言 之前我一直对于“最大似然估计”犯迷糊,今天在看了陶轻松.忆臻.nebulaf91等人的博客以及李航老师的<统计学习方法>后,豁然开朗,于是在此记下一些心得体会. “最大似然估计” ...

  5. DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

  6. [ZZ] 深度学习三巨头之一来清华演讲了,你只需要知道这7点

    深度学习三巨头之一来清华演讲了,你只需要知道这7点 http://wemedia.ifeng.com/10939074/wemedia.shtml Yann LeCun还提到了一项FAIR开发的,用于 ...

  7. SVG 学习<三>渐变

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  8. Android JNI学习(三)——Java与Native相互调用

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

  9. day91 DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

  10. Django基础学习三_路由系统

    今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...

随机推荐

  1. php yield使用

    在循环一个大数组的时候yield非常好用能节省内存. 比如有个大文件需要读取并处理,如果全部读出来太耗费内存,就可以这样做 <?php function getRows($file) { $ha ...

  2. MMORPG技能管线设计经验总结

    导语: 表现丰富.机制多变的技能作为MMORPG游戏战斗体验的核心组成部分,是吸引玩家的一大亮点,本文总结了在MMORPG技能系统设计上的一些经验,供大家参考. 1.设计思路 早期的MMORPG手游中 ...

  3. Apache APISIX 和 Kong 的选型对比

    从 API 网关核心功能点来看,两者均已覆盖: 功能 Apache APISIX Kong 动态上游 支持 支持 动态路由 支持 支持 健康检查和熔断器 支持 支持 动态SSL证书 支持 支持 七层和 ...

  4. 基于 JUnit 的全局单元测试程序

    在 Java 程序中,JUnit 是备受开发人员喜爱的单元测试工具.通常,程序员会对每个程序的每个模块写单元测试.对于小型程序来说,程序员只需要手工执行这些单元测试程序就可以,工作量并不大,但是对于中 ...

  5. Impala源代码分析(1)-Impala架构和RPC

    Leave a reply Impala总共分为3个组件:impalad, statestored, client/impala-shell.关于这三个组件的基本功能在这篇文章中已经介绍过了. Cli ...

  6. UUID和雪花(Snowflake)算法该如何选择?

    UUID 和 Snowflake 都可以生成唯一标识,在分布式系统中可以说是必备利器,那么我们该如何对不同的场景进行不同算法的选择呢,UUID 简单无序十分适合生成 requestID, Snowfl ...

  7. 基于rsync+sersync的服务器文件同步

    参考:https://github.com/wsgzao/sersync 原理 Synchronize files and folders between servers -using inotiy ...

  8. redis教程(Mac)

    1.首先,检查是否已经安装Homebrew,如果没有安装Homebrew,请先安装 2.使用Homebrew安装命令,在终端输入以下命令 brew install redis 当前默认安装5.0.8版 ...

  9. Codeforces Round 892 (Div.2)

    A. United We Stand 题解 赛时想复杂了 题目要求我们保证数组\(c\)中的数不是数组\(b\)中任意一个数的因子 我们考虑将最小值置于数组\(b\)即可 const int N = ...

  10. 【JS篇】控制子集超过一定数量开始轮播

    [JS篇]控制子集超过一定数量开始轮播, 这个是很早的时候的一个效果了,经过代码的不断迭代升级修改,现在是最封装的一版本,通过面向对象传参数,适用于任何一个需要放置 数量达到一定条件后可执行的函数 / ...