DXP TreeList 目录树

1.需求背景

需要一个支持勾选拖动节点保存各节点顺序的目录树。

2.创建目录树

treeList控件中添加两个colunm 用来显示绑定数据显示值。

接下来对treeList的属性进行设置

            // 设置列不显示
treeList.OptionsView.ShowColumns = false;
// 设置序号列不显示
treeList.OptionsView.ShowIndicator = false;
// 设置垂直线不显示
treeList.OptionsView.ShowVertLines = false;
// 设置水平线不显示
treeList.OptionsView.ShowHorzLines = false;
// 设置焦点框为行焦点
treeList.OptionsView.FocusRectStyle = DevExpress.XtraTreeList.DrawFocusRectStyle.RowFocus;
// 隐藏第一列(数据列)
treeListColumn1.Visible = false;
// 设置不可编辑
treeList.OptionsBehavior.Editable = false;
// 设置显示复选框
treeList.OptionsView.ShowCheckBoxes = true;
// 设置勾选父节点,子节点自动全选
treeList.OptionsBehavior.AllowRecursiveNodeChecking = true;

添加节点

        private TreeListNode AppendNode(PrjTableNode node, int pid)
{
TreeListNode treeListNode = null;
Action<PrjTableNode, int> ac = (arg1, arg2) =>
{
treeListNode = treeList.AppendNode(new object[] { node, node.Alias }, pid, 0, 0, 0);
};
var tt = treeList.Invoke(ac, new object[] { node, pid });
SetNodeCheckState(treeListNode);
return treeListNode;
}

主要用到treeList.AppendNode()方法,方法定义如下

 AppendNode(object nodeData, int parentNodeId, int imageIndex, int selectImageIndex, int stateImageIndex)
  • nodeData : object 类型的参数,这里传入object[]数组对象,数组对应treeList的列,这里第一列是数据,第二列用来显示,因此需要将第一列隐藏。
  • parentNodeId :父节点ID
  • imageIndex : 节点图标索引,这里没有图标就给任意一个数字
  • selectImageIndex : 节点被选择后显示的图标索引
  • stateImageIndex : 状态图标索引

此时目录树就创建好了。

2.1 设置目录树选中节点的背景色

添加CustomDrawNodeCell事件

            // 设置行背景色
treeList.CustomDrawNodeCell -= TreeList_CustomDrawNodeCell;
treeList.CustomDrawNodeCell += TreeList_CustomDrawNodeCell;

设置颜色

        private void TreeList_CustomDrawNodeCell(object sender, DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs e)
{
if (e.Node.Selected)
{
e.Appearance.BackColor = Color.FromArgb(192, 192, 255);
}
}

2.2 控制目录树节点的勾选框是否显示

添加CustomDrawNodeCheckBox事件

            // 控制复选框显隐
treeList.CustomDrawNodeCheckBox -= TreeList_CustomDrawNodeCheckBox;
treeList.CustomDrawNodeCheckBox += TreeList_CustomDrawNodeCheckBox;
        private void TreeList_CustomDrawNodeCheckBox(object sender, DevExpress.XtraTreeList.CustomDrawNodeCheckBoxEventArgs e)
{
// 满足逻辑条件的 ,将 e.Handled = true 即可
if ((e.Node.GetValue(treeListColumn1) as PrjTableNode)?.Type == ConstClass1.PRJ_TYPE_ID)
{
//e.Handled = true;
}
}

2.3 节点拖拽

这里的需求是只允许同级节点内部拖动,也不允许拖动到节点子集。

设置属性OptionsDragAndDrop.DragNodesMode = DragNodesMode.Single

添加DragOver,DragDropAfterDragNode事件

            // 设置节点拖拽
treeList.OptionsDragAndDrop.DragNodesMode = DragNodesMode.Single;
// 处理拖动时的逻辑
treeList.DragOver -= TreeList_DragOver;
treeList.DragOver += TreeList_DragOver;
// 处理拖动结束时的逻辑
treeList.DragDrop -= TreeList_DragDrop;
treeList.DragDrop += TreeList_DragDrop;
// 处理拖动后的逻辑
treeList.AfterDragNode -= TreeList_AfterDragNode;
treeList.AfterDragNode += TreeList_AfterDragNode;

DragOver 用来处理拖动时的逻辑

当有节点需要禁止拖动时,满足逻辑时,设置 e.Effect = DragDropEffects.None;即可

       private void TreeList_DragOver(object sender, DragEventArgs e)
{
var currNode = treeList.FocusedNode;
var curNodeData = currNode.GetValue(treeListColumn1) as PrjTableNode;
if (curNodeData == null)
{
return;
}
if (!curNodeData.CanDrag)
{
e.Effect = DragDropEffects.None;
}
}

DragDrop 用来处理拖动结束时的逻辑

        private void TreeList_DragDrop(object sender, DragEventArgs e)
{
// 当前节点的父节点变化,则不允许拖动
var dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode;
var sourceParent = dragNode.ParentNode.GetValue(treeListColumn1) as PrjTableNode; var targetNode = treeList.CalcHitInfo(treeList.PointToClient(MousePosition)).Node;
if (targetNode == null)
{
return;
}
PrjTableNode targetNodeParent = null;
if (targetNode.ParentNode != null)
{
targetNodeParent = targetNode.ParentNode.GetValue(treeListColumn1) as PrjTableNode;
}
// 发生跨级移动
if (sourceParent.Id != targetNodeParent.Id)
{
e.Effect = DragDropEffects.None;
return;
}
// 移到子集
if (AjustDirection(sender, e) == DragInsertPosition.AsChild)
{
e.Effect = DragDropEffects.None;
return;
}
}
        /// <summary>
/// 移动过程中的方向
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <returns></returns>
private DragInsertPosition AjustDirection(object sender, DragEventArgs e)
{
var tl = sender as TreeList;
//var dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode;
//var hit = tl.CalcHitInfo(tl.PointToClient(new Point(e.X, e.Y)));
var pi = typeof(TreeList).GetProperty("Handler", BindingFlags.Instance | BindingFlags.NonPublic);
var handler = (TreeListHandler)pi.GetValue(tl, null);
return handler.StateData.DragInfo.DragInsertPosition; }

AfterDragNode 用来处理拖动结束后的逻辑

        private void TreeList_AfterDragNode(object sender, AfterDragNodeEventArgs e)
{
// TODO:... }

3.总结

treeList是一个很强大的控件,用来处理树状结构。本次需求中,处理节点拖拽话费了较长时间,也网上找了很多博文,但是都没有直接解决我的问题,因此在这里做个笔记。

后记:纸上得来终觉浅,绝知此事要躬行

DXP TreeList 目录树的更多相关文章

  1. Java生成菜单树(目录树)的几种方式

    本文介绍两种不同生成多级目录树的方式:1. 递归生成,2.  map+list 集合生成.最下方会附上完整代码. 生成树的基本规则:子节点的par_id等于父节点的id. 1. 实体类 import ...

  2. 【.net 深呼吸】将目录树转化为文本

    大伙都知道,文件系统是树形结构的,有时候我们会想到把目录的层次结构变为纯文本形式,就像这样: ├─Windows-universal-samples-master │ ├─Samples │ │ ├─ ...

  3. python 小程序 复制目录树

    1. 将一个目录树完全复制到另外一个目录下面 import os, sys """ 复制目录树 """ maxloadsize = 1024 ...

  4. vs切换当前编辑文件时自动定位目录树

    在编辑区,切换当前编辑文件时(单击.cpp或.h文件选项卡),"解决方案资源管理器"目录树会自动定位当前编辑的文件,并以灰色标识,当一个解决方案中的工程数目数目很多,每个工程下面又 ...

  5. 14.KVM安装之脚本和镜像目录树准备

    1.php脚本需要先安装PHP环境,Apache服务器必须支持PHP $ yum install -y php    #安装PHP $ php -v                      #查看是 ...

  6. HBase 在HDFS 上的目录树

         总所周知,HBase 是天生就是架设在 HDFS 上,在这个分布式文件系统中,HBase 是怎么去构建自己的目录树的呢? 这里只介绍系统级别的目录树. 一.0.94-cdh4.2.1版本 系 ...

  7. 完整学习git三 查看暂存区目录树 git diff

    1显示暂存区中的目录树 git ls-files git ls-tree git diff 魔法 1工作区与暂存区比较 git diff 2工作区与HEAD比较 git diff HEAD 3暂存区与 ...

  8. 页面设计--Tree目录树

    Tree目录树控件属性: 根据数据集合来配置相应的信息 加载模式有自动加载.自定加载 web中显示效果图:

  9. 原创的基于HTML/CSS/JavaScript的层级目录树

    之前参加过一些基于HTML/CSS/JavaScript的项目,当在页面中需要生成一颗目录树时,总是首先想着网上有没有现成的生成树的源代码,比如dtree.zthee,或者使用一些javascript ...

  10. Linux目录树

    Linux目录树(directory tree) 分层结构(不同于数据库文件系统),单个文件/目录的最大长度为255个字符,完整路径为4096个字符 特殊的文件系统 文件系统 挂载点 说明 Root ...

随机推荐

  1. 音视频八股文(9)-- flv的h264六层结构和aac六层结构

    flv介绍 FLV(Flash Video)是Adobe公司推出的⼀种流媒体格式,由于其封装后的⾳视频⽂件体积⼩.封装简单等特点,⾮常适合于互联⽹上使⽤.⽬前主流的视频⽹站基本都⽀持FLV.采⽤FLV ...

  2. 2023-03-09:用golang调用ffmpeg,将流媒体数据(以RTMP为例)保存成本地文件(以flv为例)。

    2023-03-09:用golang调用ffmpeg,将流媒体数据(以RTMP为例)保存成本地文件(以flv为例). 答案2023-03-09: 这是最简单的收流器.本文记录一个最简单的基于FFmpe ...

  3. 2020-01-16:我截获了登录token的话,是不是就获得了登录状态,这样就不安全了。如何保证安全?

    福哥答案2020-01-06:[知乎答案:](https://www.zhihu.com/question/439602796)首先,Token 一般放在 Header 或者 Cookies 中,Ht ...

  4. 2021-04-18:给定一个二维数组matrix,里面的值不是1就是0,上、下、左、右相邻的1认为是一片岛,返回matrix中岛的数量。

    2021-04-18:给定一个二维数组matrix,里面的值不是1就是0,上.下.左.右相邻的1认为是一片岛,返回matrix中岛的数量. 福大大 答案2021-04-18: 并查集. 代码用gola ...

  5. laravel ServiceProvider 服务提供者使用案例

    1. 实例化一个类 2.全局注册这个类 3.在控制器中使用 public function register() { $this->app->singleton('wxminapp', f ...

  6. 2022年第十四届四川省大学生程序设计大赛 A

    A Adjacent Swapping 题意: 给定一个字符串,每次可以移动相邻字符,求最小移动次数可以把它变成s+s这样左右两边相同的字符串. 思路: 1:我们知道他一定是偶数长度,所以我们把字符串 ...

  7. dockder 学习第一篇

    1 docker安装 1 yum包的更新到最新 yum update 2 安装需要软件包,yum-util [root@localhost ~]# yum install -y yum-utils d ...

  8. Odoo-----计算字段、depnds,onchange 机制、模型约束

    1 计算字段和默认值问题 ​ 字段通过调用模型的方法的实时计算获得,一般都是 compute 属性为主的方法,这个计算方法通过计算self每条记录设置的的值,self 是一个有记录的有序集合,支持py ...

  9. Godot的几个附加脚本和进行继承时比较特别的特性

    注: 这是在Godot4.0中总结出的内容,并且语言是C#. 特别的,下面有的特性和C#关系比较大. 基本特性 在Godot中,为某个节点编写特别的代码时,需要为节点新建脚本,或引用已有脚本. 引用脚 ...

  10. Galaxy Release (v 21.05),众多核心技术栈变更

    2021年6月初,Galaxy Project 正式发布了 release 21.05 版本:随后6月中旬,发布该版本的 announcement 文档.这里总结一下该版本一些主要的更新内容,为关注和 ...