DevExpress11、TreeList

一、简介

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;

namespace DXApplication_1
{
    public partial class TreeListForm : DevExpress.XtraEditors.XtraForm
    {
        public TreeListForm()
        {
            InitializeComponent();
        }

        private void TreeListForm_Load(object sender, EventArgs e)
        {
            Encapsulation_CreateDataTable_1();
        }

        public DataTable Encapsulation_CreateDataTable_1()
        {
            DataTable dataTable = new DataTable();
// 此属性设为true 每个节点前会自动增加一个check框 treeList1.OptionsView.ShowCheckBoxes = true; // 此属性设为true 点击复选框时,可设置为半选状态 treeList1.OptionsBehavior.AllowIndeterminateCheckState = true
;

            dataTable.Columns.Add("ID");
            dataTable.Columns.Add("ParentID");
            dataTable.Columns.Add("AnimeName");
            

            DataRow row1 = dataTable.NewRow();
            row1["ID"] = 1;
            row1["ParentID"] = 1;
            row1["AnimeName"] = "日语";
            dataTable.Rows.Add(row1);

            DataRow row2 = dataTable.NewRow();
            row2["ID"] = 2;
            row2["ParentID"] = 1;
            row2["AnimeName"] = "未闻花名";
            dataTable.Rows.Add(row2);

            DataRow row3 = dataTable.NewRow();
            row3["ID"] = 3;
            row3["ParentID"] = 1;
            row3["AnimeName"] = "千与千寻";
            dataTable.Rows.Add(row3);

            DataRow row4 = dataTable.NewRow();
            row4["ID"] = 4;
            row4["ParentID"] = 4;
            row4["AnimeName"] = "英语";
            dataTable.Rows.Add(row4);

            DataRow row5 = dataTable.NewRow();
            row5["ID"] = 5;
            row5["ParentID"] = 4;
            row5["AnimeName"] = "这个杀手不太冷";
            dataTable.Rows.Add(row5);

            treeList1.DataSource 
= dataTable; treeList1.KeyFieldName = "ID"; treeList1.ParentFieldName = "ParentID"; treeList1.Columns[0].Caption = "Tree_1"
;
            return dataTable;
        }
    }
}

 

二、属性列表

1、OptionsSelection:

  • EnableAppearanceForcusedCell:选中的Cell的Appearance设置是否可用。默认为True;
  • EnableAppearanceForcusedRow:选中的Row的Appearance设置是否可用。默认为True
  • InvertSelection:设置选中风格是只应用于选中的Cell,还是应用于除选中的Cell之外的所有Cell。默认为False
  • MultiSelect:是否可以选择多个Node。默认为False。

2、OptionsView:

  • AutoCalcPreviewLineCount:是否自动计算预览文本行的数量。默认为True;
  • AutoWidth:是否允许列自动调整宽度;默认为True;
  • EnableAppearanceEvenRow:生成偶数Node时,是采用由TreeListAppearanceCollection.EvenRow属性提供的Appearance设置,还是采用由TreeListAppearanceCollection.Row提供的Appearance设置。默认为False,即后者;
  • EnableAppearanceOddRow:生成奇数Node时,是采用由TreeListAppearanceCollection.OddRow属性提供的Appearance设置,还是采用由TreeListAppearanceCollection.Row提供的Appearance设置。默认为False,即后者;
  • ShowButtons:是否显示展开与收缩按钮。默认为True;
  • ShowCloumns:是否显示列标题。默认为True;
  • ShowFocusedFrame:在获得焦点的Cell上,是否显示焦点框架。默认为True;
  • ShowHorzLines:是否显示水平线。默认为True;
  • ShowIndentAsRowStyle:是否用相应Node的Appearance设置来生成Tree的缩进。默认为False
  • ShowIndicator:是否显示Node的指示符面板。默认为True;
  • ShowPreview:是否显示预览。默认为False;
  • ShowRoot:是否在根Node间显示连接线。默认为True;
  • ShowRowFooterSummary:是否显示分组脚注。默认为False;
  • ShowSummaryFooter:是否显示摘要脚注。默认为False;
  • ShowVertLines:是否显示垂直线。默认为True;
  • ShowCheckBoxes属性控制是否每项前显示CheckBox,该属性属于bool类型

3、SelectImageList:选中Node时,显示图片的列表

4、StateImageList:指明Node状态的图片的列表

三、事件

    AfterCheckNode事件是当选择CheckBox时所触发的事件;

四、使用

1、 如何隐藏TreeList的列头

   设置TreeList的OptionsView的ShowColumns属性为:False

2、 节点折叠和展开

    treeList1.ExpandAll();

    以及TreeNode.Expand = false;

    或者你可以控制展开的层数 treeList1.ExpandLevel = 10;//表示: 展开10层

  // 第一层下的所有接点展开

  treeList1.Nodes[0].ExpandAll();

    所有节点折叠 :treeList1.CollapseAll();

3、 如何让TreeList的每个结点高亮显示?

代码如下:

private void treeList1_CustomDrawNodeCell(object sender, DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs e){
      TreeList node = sender as TreeList;
      if (e.Node == node.FocusedNode){
        e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
        
        Rectangle r = new Rectangle(e.EditViewInfo.ContentRect.Left, e.EditViewInfo.ContentRect.Top,
        Convert.ToInt32(e.Graphics.MeasureString(e.CellText,  treeList1.Font).Width + 1), Convert.ToInt32(e.Graphics.MeasureString(e.CellText,treeList1.Font).Height));
        
        e.Graphics.FillRectangle(SystemBrushes.Highlight, r);
        e.Graphics.DrawString(e.CellText, treeList1.Font, SystemBrushes.HighlightText, r);
        e.Handled = true;
      }
    }

4、 数据绑定最基本的两个属性:KeyFieldName和ParentFieldName。

(这两个属性一设置就基本上可以实现分级了)

可以通过代码的编写实现,也可以直接在属性里面直接实现。

这种数据库设计是比较常见的,一般数据满足树形关系就可以这样设计。

绑定数据时,只需指定DataSource为对应 的DataTable,指定KeyFieldName为表主键字段,ParentFieldName为表指向主键的外键字段名。

private void BindData()
   {
     this.treeList_office.DataSource = dataTable_office;
     dataTable_office.KeyFieldName = "OfficeID";

     // dataTable_office.DataMember = "OfficeName";
     dataTable_office.Columns["OfficeName"].Caption = "办公室名称";
     dataTable_office.ParentFieldName = "ParentOfficeID";
   }

5、 选择某一节点时,该节点的子节点全部选择 ,取消某一节点时,该节点的子节点全部取消选择

由此确定方法的两个参数:TreeListNode和CheckState。

遍历该节点及其子孙,并将其选中状态设置为该节点的状态即可。

/// 选择某一节点时,该节点的子节点全部选择 取消某一节点时,该节点的子节点全部取消选择
  /// <param name="node"></param>
  /// <param name="state"></param>
  private void SetCheckedChildNodes(TreeListNode node, CheckState check)
  {
    for (int i = 0; i < node.Nodes.Count; i++)
    {
      node.Nodes[i].CheckState = check;
      // 递归
      SetCheckedChildNodes(node.Nodes[i], check);
    }
  }
/// 某节点的子节点全部选择时,该节点选择  
   /// 某节点的子节点未全部选择时,该节点不选择
   /// <param name="node"></param>
   /// <param name="check"></param>
   private void SetCheckedParentNodes(TreeListNode node, CheckState check)
   {
     if (node.ParentNode != null)
     {
       CheckState parentCheckState = node.ParentNode.CheckState;
       CheckState nodeCheckState;
       for (int i = 0; i < node.ParentNode.Nodes.Count; i++)
       {
         nodeCheckState = (CheckState)node.ParentNode.Nodes[i].CheckState;
         // 只要任意一个与其选中状态不一样即父节点状态不全选
         if (!check.Equals(nodeCheckState)) 
         {
           parentCheckState = CheckState.Unchecked;
           break;
         }
         // 否则(该节点的兄弟节点选中状态都相同),则父节点选中状态为该节点的选中状态
         parentCheckState = check;
       }
       node.ParentNode.CheckState = parentCheckState;
       // 遍历上级节点
       SetCheckedParentNodes(node.ParentNode, check);
     }
   }

上两步写好了,别忘了上面的两个方法在TreeList_AfterCheckNode里面触发:

private void tlOffice_AfterCheckNode(object sender, DevExpress.XtraTreeList.NodeEventArgs e)
{
  SetCheckedChildNodes(e.Node, e.Node.CheckState);
  SetCheckedParentNodes(e.Node, e.Node.CheckState);
}

6、 获取选中的复选框数据列表

private List<int> lstCheckedOfficeID = new List<int>();//选择局ID集合
   /// 获取选择状态的数据主键ID集合
   /// <param name="parentNode">父级节点</param>
private void GetCheckedOfficeID(TreeListNode parentNode)
   {
     if (parentNode.Nodes.Count == 0)
     {
       // 递归终止
       return;
     }
     foreach (TreeListNode node in parentNode.Nodes)
     {
       if (node.CheckState == CheckState.Checked)
       {
         DataRowView drv = tlOffice.GetDataRecordByNode(node) as DataRowView;//关键代码,就是不知道是这样获取数据而纠结了很久(鬼知道可以转换为DataRowView啊)
         if (drv != null)
         {
           int OfficeID = (int)drv["OfficeID"];
           lstCheckedOfficeID.Add(OfficeID);
         }
       }
       GetCheckedOfficeID(node);
     }
   }

  下面测试获取主键列表:

private void btnCheck_Click(object sender, EventArgs e)
   {
     this.lstCheckedOfficeID.Clear();
     if (tlOffice.Nodes.Count > 0)
     {
       foreach (TreeListNode root in tlOffice.Nodes)
       {
         GetCheckedOfficeID(root);
       }
     }
     string idStr = string.Empty;
     foreach (int id in lstCheckedOfficeID)
     {
       idStr += id + " ";
     }
     MessageBox.Show(idStr);
   }
原文地址:https://www.cnblogs.com/springsnow/p/10298967.html