经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
DXP TreeList 目录树
来源:cnblogs  作者:宣君  时间:2023/8/4 9:07:54  对本文有异议

DXP TreeList 目录树

1.需求背景

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

image

2.创建目录树

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

image

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

  1. // 设置列不显示
  2. treeList.OptionsView.ShowColumns = false;
  3. // 设置序号列不显示
  4. treeList.OptionsView.ShowIndicator = false;
  5. // 设置垂直线不显示
  6. treeList.OptionsView.ShowVertLines = false;
  7. // 设置水平线不显示
  8. treeList.OptionsView.ShowHorzLines = false;
  9. // 设置焦点框为行焦点
  10. treeList.OptionsView.FocusRectStyle = DevExpress.XtraTreeList.DrawFocusRectStyle.RowFocus;
  11. // 隐藏第一列(数据列)
  12. treeListColumn1.Visible = false;
  13. // 设置不可编辑
  14. treeList.OptionsBehavior.Editable = false;
  15. // 设置显示复选框
  16. treeList.OptionsView.ShowCheckBoxes = true;
  17. // 设置勾选父节点,子节点自动全选
  18. treeList.OptionsBehavior.AllowRecursiveNodeChecking = true;

添加节点

  1. private TreeListNode AppendNode(PrjTableNode node, int pid)
  2. {
  3. TreeListNode treeListNode = null;
  4. Action<PrjTableNode, int> ac = (arg1, arg2) =>
  5. {
  6. treeListNode = treeList.AppendNode(new object[] { node, node.Alias }, pid, 0, 0, 0);
  7. };
  8. var tt = treeList.Invoke(ac, new object[] { node, pid });
  9. SetNodeCheckState(treeListNode);
  10. return treeListNode;
  11. }

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

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

此时目录树就创建好了。

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

添加CustomDrawNodeCell事件

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

设置颜色

  1. private void TreeList_CustomDrawNodeCell(object sender, DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs e)
  2. {
  3. if (e.Node.Selected)
  4. {
  5. e.Appearance.BackColor = Color.FromArgb(192, 192, 255);
  6. }
  7. }

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

添加CustomDrawNodeCheckBox事件

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

2.3 节点拖拽

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

设置属性OptionsDragAndDrop.DragNodesMode = DragNodesMode.Single

添加DragOver,DragDropAfterDragNode事件

  1. // 设置节点拖拽
  2. treeList.OptionsDragAndDrop.DragNodesMode = DragNodesMode.Single;
  3. // 处理拖动时的逻辑
  4. treeList.DragOver -= TreeList_DragOver;
  5. treeList.DragOver += TreeList_DragOver;
  6. // 处理拖动结束时的逻辑
  7. treeList.DragDrop -= TreeList_DragDrop;
  8. treeList.DragDrop += TreeList_DragDrop;
  9. // 处理拖动后的逻辑
  10. treeList.AfterDragNode -= TreeList_AfterDragNode;
  11. treeList.AfterDragNode += TreeList_AfterDragNode;

DragOver 用来处理拖动时的逻辑

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

  1. private void TreeList_DragOver(object sender, DragEventArgs e)
  2. {
  3. var currNode = treeList.FocusedNode;
  4. var curNodeData = currNode.GetValue(treeListColumn1) as PrjTableNode;
  5. if (curNodeData == null)
  6. {
  7. return;
  8. }
  9. if (!curNodeData.CanDrag)
  10. {
  11. e.Effect = DragDropEffects.None;
  12. }
  13. }

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

  1. private void TreeList_DragDrop(object sender, DragEventArgs e)
  2. {
  3. // 当前节点的父节点变化,则不允许拖动
  4. var dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode;
  5. var sourceParent = dragNode.ParentNode.GetValue(treeListColumn1) as PrjTableNode;
  6. var targetNode = treeList.CalcHitInfo(treeList.PointToClient(MousePosition)).Node;
  7. if (targetNode == null)
  8. {
  9. return;
  10. }
  11. PrjTableNode targetNodeParent = null;
  12. if (targetNode.ParentNode != null)
  13. {
  14. targetNodeParent = targetNode.ParentNode.GetValue(treeListColumn1) as PrjTableNode;
  15. }
  16. // 发生跨级移动
  17. if (sourceParent.Id != targetNodeParent.Id)
  18. {
  19. e.Effect = DragDropEffects.None;
  20. return;
  21. }
  22. // 移到子集
  23. if (AjustDirection(sender, e) == DragInsertPosition.AsChild)
  24. {
  25. e.Effect = DragDropEffects.None;
  26. return;
  27. }
  28. }
  1. /// <summary>
  2. /// 移动过程中的方向
  3. /// </summary>
  4. /// <param name="sender"></param>
  5. /// <param name="e"></param>
  6. /// <returns></returns>
  7. private DragInsertPosition AjustDirection(object sender, DragEventArgs e)
  8. {
  9. var tl = sender as TreeList;
  10. //var dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode;
  11. //var hit = tl.CalcHitInfo(tl.PointToClient(new Point(e.X, e.Y)));
  12. var pi = typeof(TreeList).GetProperty("Handler", BindingFlags.Instance | BindingFlags.NonPublic);
  13. var handler = (TreeListHandler)pi.GetValue(tl, null);
  14. return handler.StateData.DragInfo.DragInsertPosition;
  15. }

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

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

3.总结

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

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

原文链接:https://www.cnblogs.com/ycit/p/17604994.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号