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. 你知道Object类和Objects的常用方法吗

    文章目录 Object的常用方法 Objects的常用方法 hashCode hash isNull equals requireNonNull compare nonNull 大家好,Leo又来了! ...

  2. OFFICE-Excel_在只有清单没有定额人材机的情况下筛选工程量的操作

    目的 一个来自东莞的项目需要清单里面所有的电线电缆的量和价,但是由于东莞市的投标清单只需要清单报价即可,没有定额,也就没有人材机,所以就只能依靠清单来剔除量,但是有几个问题,众所周知电线电缆这种材料一 ...

  3. 2020-10-31:java中LinkedTransferQueue和SynchronousQueue有什么区别?

    福哥答案2020-11-01:SynchronousQueue:线程A使用put将数据添加到队列,如果没有其他线程使用take去获取数据,那么线程A阻塞,直到数据被其他线程获取,同理 如果线程B从队列 ...

  4. 2021-06-17:生成长度为size的达标数组,什么叫达标?达标:对于任意的 i<k<j,满足 [i] + [j] != [k] * 2。给定一个正数size,返回长度为size的达标数组。

    2021-06-17:生成长度为size的达标数组,什么叫达标?达标:对于任意的 i<k<j,满足 [i] + [j] != [k] * 2.给定一个正数size,返回长度为size的达标 ...

  5. 认识CPU底层原理(1)——MOSFET

    本文为B站UP主硬件茶谈制作的系列科普<[硬件科普]带你认识CPU>系列的学习笔记,仅作个人学习记录使用,如有侵权,请联系博主删除 近年来,由于国内外各种因素影响,半导体行业逐渐被推向风口 ...

  6. Spring源码:Bean生命周期(终章)

    前言 本系列前面讲解了Spring的bean定义.bean实例化.bean初始化等生命周期.这些步骤使我们能够了解bean从创建到准备好使用所经历的过程.但是,除了这些步骤,bean的销毁也是非常重要 ...

  7. 第一单元 .Net 平台介绍

    第一单元 .Net 平台介绍 学习编程,电脑基本配置(当然配置越高越好): 内存 :初期学习8 G,后期可能跟不上, 最好16 G以上 硬盘:500 G,5400 转速,至少C盘是固态,全是固态最好 ...

  8. 2023-06-03:redis中pipeline有什么好处,为什么要用 pipeline?

    2023-06-03:redis中pipeline有什么好处,为什么要用 pipeline? 答案2023-06-03: Redis客户端执行一条命令通常包括以下四个阶段: 1.发送命令:客户端将要执 ...

  9. 数据科学工具 Jupyter Notebook 教程(二)

    Jupyter Notebook 是一个把代码.图像.注释.公式和作图集于一处,实现可读性分析的交互式笔记本工具.借助所谓的内核(Kernel)的概念,Jupyter Notebook 可以同时支持包 ...

  10. BGP 反射器;BGP联盟

    目录 BGP反射器 实验拓扑 实验需求 实验步骤 在R2上查看BGP邻居表 在R2上做反射器 在R3上查看1.1.1.1 路由表,进行观察 在R3上查看1.1.1.1 路由详细信息 BGP联盟实验 实 ...