【Syncfusion系列】Diagram 杂谈第一篇
前言
我认为 Diagram
是 Syncfusion
中首屈一指的优秀控件!最近在写一个工作流引擎,前端界面就用的是Diagram
,接下来就来看一看。
Diagram的事件
查看 SfDiagram的属性,如果想实现什么事件,就看这些Command结尾的。
这里,我想看看 双击Diagram中的一个节点,能触发什么事件。
于是,我找到了,ItemDoubleTappedCommand!
我使用 prism 的方式 进行绑定:
ItemDoubleTappedCommand="{Binding ItemDoubleTappedCmd}"
其实这个并不是一个事件(并不能双击自动产生一个事件),而是封装好的命令, 看看源码就知道:
//
// 摘要:
// Gets or sets the itemdoubletappedcommand to invoke when double// click on the diagram
// or diagram elements.
public ICommand ItemDoubleTappedCommand
{get{return (ICommand)GetValue(ItemDoubleTappedCommandProperty);}set{SetValue(ItemDoubleTappedCommandProperty, value);}
}
注意,这个命令,不管是双击diagram控件或者是其中的元素,都会触发该事件。并且双击节点的不同位置,触发传递的参数还会有所不同,后面介绍。
ItemDoubleTappedCmd = new DelegateCommand<ItemDoubleTappedEventArgs>((args) => {try{//注意这里点的位置不同,返回的参数不一样,但是都可以获取到Node!VisualNode node = args.OriginalSource as VisualNode;if (node == null){node = args.Item as VisualNode;if (node == null){return;} }
});
后台实现命令如上,这样只要点击在控件上,我都能获取到node对象!
如果点击在节点的说明上,args的值如下:
此时,node的相关信息包含在,OriginalSource里面。
如果点击没在节点的说明上(说明的周边),args的值如下:
此时,node的相关信息包含在,Item里面。
如果此时你没点任何节点,而是双击在了空白处!
此时 Item里面包含的是 Diagram 对象。
这里讲的是 ItemDoubleTappedCommand 双击的事件,那么其他的都大同小异!
如何通过node拿到Diagram
通过上面那个事件,我们可以拿到当前被双击的Node对象,那么如何通过Node拿到Diagram 对象呢?
//双击触发节点ItemDoubleTappedCmd = new DelegateCommand<ItemDoubleTappedEventArgs>(async(args) => {try{//注意这里点的位置不同,返回的参数不一样,但是都可以获取到Node!VisualNode node = args.OriginalSource as VisualNode;if (node == null){node = args.Item as VisualNode;if (node == null){return;} }#region 这里开始拿对象//-- 这里演示了,如何通过node得到diagramcontrol!!!!var a = node.Info as IGroupableInfo;var manager = a.Graph.CommandManager;var diagramcontrol = manager.View as SfDiagram;#endregion}catch (Exception ex){MessageBox.Show(ex.Message);}});
通过Node拿到Diagram确实废了我一番功夫,有很多类是对外隐藏的,所以没办法直接进行强制转换,Diagram的相关代码中有很多,先转为接口,才能拿到某些属性的例子。
比如
public NodeViewModel FindNextNode(NodeViewModel node){var out_nodes = (node.Info as INodeInfo).OutNeighbors as IEnumerable<object>;if (out_nodes != null && (out_nodes).Count() > 0){foreach (NodeViewModel outnode in out_nodes){if (node != outnode){return outnode;}}}return null;}
我们需要多熟悉他们的数据结构,并熟悉这种写法。
命令取消
Diagram 封装了很多自带的命令,比如对齐,旋转,复制,剪切,撤回,全选,等等,一共48个,如下图:,
这些命令都是开箱即用的,非常方便! 但是有的时候,我却是想去掉某些命令。
比如,它自带的编辑命令,当我们双击的时候,会触发编辑命令,节点会进入编辑状态,这个是我不想要的,(我想实现弹窗)
那如何取消呢?我们继续完善代码!
//双击触发节点
ItemDoubleTappedCmd = new DelegateCommand<ItemDoubleTappedEventArgs>(async(args) => {try{//注意这里点的位置不同,返回的参数不一样,但是都可以获取到Node!VisualNode node = args.OriginalSource as VisualNode;if (node == null){node = args.Item as VisualNode;if (node == null){return;} }#region 这里用来取消双击导致的编辑这个副作用, Cancel命令是一个多功能命令,可以根据上下文执行不同的操作,如停止编辑注释并接受当前的编辑结果,或者清除图表元素的选择和键盘焦点。await Task.Delay(50);//-- 这里演示了,如何通过node得到diagramcontrol!!!!var a = node.Info as IGroupableInfo;var manager = a.Graph.CommandManager;var diagramcontrol = manager.View as SfDiagram;// 得到graphinfo IGraphInfo graphinfo = diagramcontrol.Info as IGraphInfo;// 命令取消!graphinfo.Commands.Cancel.Execute(null); #endregion}catch (Exception ex){MessageBox.Show(ex.Message);}});
那效果如下,明显有个取消的过程:
这里,你会不会好奇,代码里面为啥,加了一个异步?await Task.Delay(50);
你可以尝试把这个异步去掉,你会发现没有效果!
其实这段代码必须,写道//双击触发节点
ItemDoubleTappedCmd = new DelegateCommand(async(args) => {
这个函数外面才会有效,就是如果这个函数没退出,直接取消是没有用的!
我遇到过,很多情况都是这样。
不过,我发现了一个更优雅的写法,就是这个异步。
主线程,遇到这个await Task.Delay(50); 其实就会挑走,从而出了这个函数。
当50毫秒时间一到,就会又调回来,这样就和写道外面是一样的了,于是就生效了!!!!
是不是又学了一招呢?(手动狗头~~)