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,DragDrop,AfterDragNode事件

            // 设置节点拖拽
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. 继承 extends

    首先是基础的继承关系,用extend就可以继承. 再者是继承的东西,包括:变量(也包括类变量).全部非私有的属性和方法(除了父类的构造方法) 注:构造方法 class C{ public C() { ...

  2. MySQL百万数据深度分页优化思路分析

    业务场景 一般在项目开发中会有很多的统计数据需要进行上报分析,一般在分析过后会在后台展示出来给运营和产品进行分页查看,最常见的一种就是根据日期进行筛选.这种统计数据随着时间的推移数据量会慢慢的变大,达 ...

  3. 2022-10-15:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。 你可以按 任意顺序 返回答案。 要求时间复杂度O(N)。 输入: nums = [1,1,1

    2022-10-15:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素. 你可以按 任意顺序 返回答案. 要求时间复杂度O(N). 输入: nums = [1,1,1 ...

  4. AccessToken、for_user、get_token

    在Django REST framework的SimpleJWT库中,AccessToken是一个类,用于表示一个JSON Web Token (JWT)中的访问令牌部分.访问令牌是一种常见的身份验证 ...

  5. Sql Server维护计划事务日志找不到目标数据库

    1.发现事务日志备份突然停止了 2.查看维护计划中的事务日志设置 3.发现备份任务中,事务日志需要指向的数据库不在 4.进入数据库属性 5.在选项中将恢复模式改为"完整"

  6. C++实现查询本机信息并且上报

    业务需求 共享文件夹.盘会导致系统安全性下降,故IT部门需要搜集公司中每台电脑的共享情况,并且进行上报 关键字 WMI查询.Get请求.C++网络库mongoose 前置需要 1.简单C++语法知识2 ...

  7. 2013年蓝桥杯C/C++大学A组省赛真题(排它平方数)

    题目描述: 小明正看着 203879 这个数字发呆. 原来,203879 * 203879 = 41566646641 这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位上的数字都是 ...

  8. 代码随想录算法训练营Day31 贪心算法| 理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

    代码随想录算法训练营 理论基础 什么是贪心 贪心的本质是选择每一阶段的局部最优,从而达到全局最优. 每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优. 贪心的套路(什么时候用贪心) 贪心 ...

  9. OpenOffice4.1.6 linux安装/卸载教程

    以下是centos的安装方法 1.先安装并配置好jdk 2.拷贝 把Apache_OpenOffice_4.1.6_Linux_x86-64_install-rpm_zh-CN.tar.gz拷贝到自己 ...

  10. 【Python入门教程】Python常用表格函数&操作(xlrd、xlwt、openpyxl、xlwings)

    ​         在我们使用Python时,避免不了与Excel打交道.同样Python的三方库和代码的简洁性也为我们处理大数据提供了便利.今天给大家介绍一下常用的处理表格的函数,同时还有一些常用的 ...