自学内容网 自学内容网

【Syncfusion系列】Diagram 杂谈第一篇

前言

我认为 DiagramSyncfusion 中首屈一指的优秀控件!最近在写一个工作流引擎,前端界面就用的是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毫秒时间一到,就会又调回来,这样就和写道外面是一样的了,于是就生效了!!!!
是不是又学了一招呢?(手动狗头~~)


原文地址:https://blog.csdn.net/songhuangong123/article/details/143633472

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!