天天看点

DevExpress控件XtraTreeList的使用心得外观拖曳操作节点搜索过滤

数据展示

数据源绑定 需要设置KeyFieldName和ParentFieldName后绑定数据

treeList1.DataSource = dataTable1;

且KeyFieldName列不能存在重复的数据

手动增加节点

[csharp]  view plain  copy

  1. var node = treeList1.AppendNode("", null);  

注:该方法有多个重载,可灵活设置节点的父节点,图标,勾选状态,tag等

设置node上的数据

[csharp]  view plain  copy

  1. node.SetValue(treeListColumn1, obj1);  
  2. node.Tag = obj2;  

外观

自定义设置节点的图标(需要绑定一个imageCollection给TreeList的SelectImageList)

[csharp]  view plain  copy

  1. private void treeListMaster_CustomDrawNodeImages(object sender, DevExpress.XtraTreeList.CustomDrawNodeImagesEventArgs e)  
  2. {  
  3.     var index = e.Node.GetValue("IMAGEINDEX");  
  4.     if (index.ToString() != string.Empty)  
  5.     {  
  6.         e.SelectImageIndex = Convert.ToInt32(index);  
  7.     }  
  8. }  

其他外观设置基本都在OptionsView下面,可以设置:

是否显示行头,列头,水平线,垂直线,勾选框等。

OptionsFind下可以设置搜索栏的显示方式,是否显示搜索,清空按钮等。但是这个自带的搜索比较鸡肋,当一个节点满足条件,但是其父节点不满足条件时这个节点也无法显示。

除非事先调用treeList1.ExpandAll();将节点全部展开显示,当数据比较大的时候也是比较麻烦的,后面会介绍一种自定义的方法。

拖曳操作

如果需要从外面拖入数据,需要设置

treeList1.AllowDrop = true;

如果需要内部拖曳节点,需要设置

treeList1.OptionsBehavior.DragNodes = true;

相关的几个事件:

DragEnter——当拖曳进入到treeList中时

DragOver——相当于在treeList上的MouseMove

DragDrop——拖曳结束松开鼠标时

DragLeave——拖曳节点出treeList时

从外部控件(比如GridControl)拖曳数据到树上,流程:

//1

Grid的MouseMove事件判断是否左键按下,执行treeList1.DoDragDrop(yourData, DragDropEffects.Copy);

//2

treeList的DragEnter事件,执行e.Effect = DragDropEffects.Copy;//可以执行判断,如果不满足可赋值DragDropEffects.None禁止拖曳操作

//3

treeList的DragDrop事件,获取数据e.Data.GetData(typeof(YourType)) as YourType,并判断当前节点:

var hi = treeListMaster.CalcHitInfo(treeListMaster.PointToClient(new Point(e.X, e.Y)));

var targetNode = hi.Node;

此处可通过hi.HitInfoType判断当前拖放的位置,是Cell,Column,Row,StateImage,Button,FilterPanel,ScrollBar,CheckBox....

然后执行treeList1.AppendNode(...);即可。

将树节点拖出控件执行删除操作,想当然地在DragLeave中操作,问题来了:

1.操作后,treeList依然认为在执行Drag操作,除非找到一个时机将DragDropEffects置为None;

2.体验不好,鼠标刚刚离开树,还没抬起左键,提示的MessageBox就弹出来了,不是想要的效果;

多次实验后还是换为另一种思路(这其实是DevExpress的Demo):

在treeList外部放置一个label,图标设置为垃圾桶:        

[csharp]  view plain  copy

  1. private void labelControl1_DragEnter(object sender, DragEventArgs e)  
  2. {  
  3.     e.Effect = DragDropEffects.Copy;  
  4.     labelControl1.Appearance.ImageIndex = 1;//换为打开的垃圾桶  
  5. }  
  6. private void labelControl1_DragDrop(object sender, DragEventArgs e)  
  7. {  
  8.     //这里执行删除节点操作  
  9.     DeleteNode();  
  10.     labelControl1.Appearance.ImageIndex = 0;//换为关闭的垃圾桶  
  11. }  
  12. private void labelControl1_DragLeave(object sender, EventArgs e)  
  13. {  
  14.     labelControl1.Appearance.ImageIndex = 0;//换位关闭的垃圾桶  
  15. }  

树内部拖曳,移动或节点排序也可以在DragDrop中操作

[csharp]  view plain  copy

  1. treeList1.SetNodeIndex(dragnode, treeList1.GetNodeIndex(targetnode));  

然后保存这个顺序即可。

问题来了:如何判断是移动节点还是排序?在拖曳的时候树控件虽然会提示箭头(向上/下表示移动,向右表示加为子节点),但是在DragDrop的代码中却无法判断这个状态。

无奈只好改为其他的事件来处理移动节点和节点排序:

AfterDragNode——拖曳节点结束后触发

通过比对dragNode的拖曳前后的父节点,判断是排序还是移动节点。

其他的还有DragObjectDrop,这个名字比较坑,其实只在拖曳treeListColumn时触发。

节点搜索过滤

前面提到treeList提供了OptionsFind,可以展示一个Find框,可以将任何匹配的文字高亮,如果打开了FilterNode选项还可以实现节点过滤。但是存在一个问题:

如果某节点匹配条件,但其父节点不匹配,该节点仍被过滤掉。除非在Find之前将树全部展开treeList1.ExpandAll();明显我们不希望这样。

根据DevExpress的官方答复,他们会在后续版本中提供一个新的OptionsFilter.FilterMode:Extended,但是目前的版本还没有。

实现方法,放置一个ButtonEdit在树控件的上方,并实现一个FilterNodeOperation类:

[csharp]  view plain  copy

  1. class FilterNodeOperation : TreeListOperation  
  2. {  
  3.     string pattern;  
  4.     public FilterNodeOperation(string _pattern)  
  5.     {  
  6.         pattern = _pattern;  
  7.     }  
  8.     public override void Execute(TreeListNode node)  
  9.     {  
  10.         if (NodeContainsPattern(node, pattern))  
  11.         {  
  12.             node.Visible = true;  
  13.             //if (node.ParentNode != null)  
  14.             //    node.ParentNode.Visible = true;  
  15.             //必须要递归查找其父节点全部设置为可见  
  16.             var pNode = node.ParentNode;  
  17.             while (pNode != null)  
  18.             {  
  19.                 pNode.Visible = true;  
  20.                 pNode = pNode.ParentNode;  
  21.             }  
  22.         }  
  23.         else  
  24.             node.Visible = false;  
  25.     }  
  26.     bool NodeContainsPattern(TreeListNode node, string pattern)  
  27.     {  
  28.         foreach (TreeListColumn col in node.TreeList.VisibleColumns)  
  29.         {  
  30.             if (node.GetDisplayText(col).Contains(pattern))  
  31.                 return true;  
  32.         }  
  33.         return false;  
  34.     }  
  35. }  
  36. //在ButtonEdit的ButtonClick事件中执行这个Operation:  
  37. private void buttonEdit1_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)  
  38. {  
  39.     var operation = new FilterNodeOperation(buttonEdit1.EditValue != null ? buttonEdit1.EditValue.ToString() : "");  
  40.     treeListMaster.NodesIterator.DoOperation(operation);  
  41. }

原文地址 http://blog.csdn.net/davinciyxw/article/details/40779573

继续阅读