DevExpress.XtraTreeList.TreeList + Winform + Access2013 使用实例(一)
在WinForm开发过程中使用到了第三方控件DevExpress中的TreeList,为了方便大家以及后面的查阅,特此将开发过程中的一些经验写出来供大家参考,包括了TreeList的一些外观现实,节点获取,以及Access数据库的批量存储操作等。本文同时也参考了网上的一些资料,特此向大神们致敬!
TreeList的重要属性
关于绑定数据的属性
在TreeList中,绑定数据时有两个重要的基本属性:KeyFieldName,以及ParentFieldName。通过这两个基本属性的设置,即可实现层级结构显示。
在KeyFieldName以及ParentFieldName中分别绑定相应的数据表字段名
数据库设计及其数据如下图:
绑定数据库的操作方法在后面再详细讲解。
关于显示CheckBox的属性
只需要设置OptionsView.ShowCheckBoxes = True
即可
关于Checkbox显示3种选中状态
需要设置OptionsBehavior.AllowIndeterminateCheckState = True
即可
关于如何显示这三种选中状态,在后面详细讲解。
关于设置TreeList是否可编辑
有时候,我们并不希望在单击TreeList单元格的时候,出现单元格可以编辑的情况,此时就需要设置TreeList的可编辑属性了。设置方法为OptionsBehavior.Editable = False
。
显示CheckBox的三种选中状态
CheckBox的三种显示状态如下:
其具体代码如下
private void treeList1_BeforeCheckNode(object sender, DevExpress.XtraTreeList.CheckNodeEventArgs e){ e.State = (e.PrevState == CheckState.Checked ? CheckState.Unchecked : CheckState.Checked);}private void treeList1_AfterCheckNode(object sender, DevExpress.XtraTreeList.NodeEventArgs e) { SetCheckedChildNodes(e.Node, e.Node.CheckState); SetCheckedParentNodes(e.Node, e.Node.CheckState); }/// <summary>/// 设置子节点的状态/// </summary>/// <param name="node"></param>/// <param name="check"></param>private void SetCheckedChildNodes(DevExpress.XtraTreeList.Nodes.TreeListNode node, CheckState check){ for (int i = 0; i < node.Nodes.Count; i++) { node.Nodes[i].CheckState = check; SetCheckedChildNodes(node.Nodes[i], check); }}/// <summary>/// 设置父节点的状态/// </summary>/// <param name="node"></param>/// <param name="check"></param>private void SetCheckedParentNodes(DevExpress.XtraTreeList.Nodes.TreeListNode node, CheckState check){ if (node.ParentNode != null) { bool b = false; CheckState state; for (int i = 0; i < node.ParentNode.Nodes.Count; i++) { state = (CheckState)node.ParentNode.Nodes[i].CheckState; if (!check.Equals(state)) { b = !b; break; } } node.ParentNode.CheckState = b ? CheckState.Indeterminate : check; SetCheckedParentNodes(node.ParentNode, check); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
获取TreeList选中的节点
获取方法如下:
private List<string> lstCheckedKeyID = new List<string>();//选择KeyID集合/// <summary>/// 获取选择状态的数据主键ID集合/// </summary>/// <param name="parentNode">父级节点</param>private void GetCheckedKeyID(TreeListNode parentNode){ if (parentNode.Nodes.Count == 0) { return;//递归终止 } foreach (TreeListNode node in parentNode.Nodes) { if (node.CheckState == CheckState.Checked) { DataRowView drv = treeList1.GetDataRecordByNode(node) as DataRowView;//关键代码,就是不知道是这样获取数据而纠结了很久(鬼知道可以转换为DataRowView啊) if (drv != null) { string KeyFieldName = (string)drv["KeyFieldName"]; lstCheckedKeyID.Add(KeyFieldName); } } GetCheckedKeyID(node); }}/// <summary>/// 获取选中的节点/// </summary>/// <param name="tree"></param>private void findOrigin(DevExpress.XtraTreeList.TreeList tree){ this.lstCheckedKeyID.Clear(); if (tree.Nodes.Count > 0) { foreach (TreeListNode root in tree.Nodes) { GetCheckedKeyID(root); } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
当需要获取到当前所选取的节点时,直接在相应时间中调用findOrigin(treeList1);
即可。
当时使用这个方法的时候发现,获取的节点并不全。比如说,当前表中只有父节点,如在表中的俄罗斯,选中它,运行上述代码,并不能获取到其KeyFieldName;再比方说,选中了南京之后,只能获取到南京和江苏省的KeyFieldName,并不能获取到中国的KeyFieldName。
上述问题的解决方法之一
在获取到节点之后,将其及与之对应的层次结构存进数据表中。由于在上一段中获取的节点并不全面,所以
我只能在另起炉灶获取到所有应该存储的节点。
/// <summary>/// 比较当前Key与已经存储的Key,不同则添加/// </summary>/// <param name="list"></param>/// <param name="strID"></param>private void getDistinctID(List<string> list, string strID){ if (!list.Contains(strID)) { list.Add(strID); } }/// <summary>/// 获取当前集合中字符串长度的最大值/// </summary>/// <param name="list">集合</param>/// <returns></returns>private int getMaxLength(List<string> list){ int MaxLength=0; foreach(string strID in list) { if(MaxLength<strID.Length) { MaxLength = strID.Length; } } return MaxLength;}/// <summary>/// 找到当前所有需要保存的节点/// </summary>/// <param name="list"></param>/// <returns></returns>private List<string> getAllKeys(List<string> list){ List<string> MaxLengthList = new List<string>(); List<string> AllKeysList = new List<string>(); int MaxLength = getMaxLength(list); if (MaxLength > 1) { //获得最长KeyFieldName foreach(string strID in list) { if(strID.Length==MaxLength) { getDistinctID(MaxLengthList, strID); getDistinctID(AllKeysList, strID); } } for(int i=0;i<MaxLengthList.Count;i++) { for(int j=1;j<MaxLength;j++) { getDistinctID(AllKeysList, MaxLengthList[i].Substring(0, j)); } } } return AllKeysList;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
通过以上方法可以获得相应的所有的KeyFieldName。
上述问题的解决方法之二
GetCheckedKeyID函数修改如下:
/// <summary>/// 获取选择状态的数据主键ID集合/// </summary>/// <param name="parentNode">父级节点</param>private void GetCheckedKeyID(TreeListNode parentNode){ if (parentNode.Nodes.Count == 0) { return;//递归终止 } if(parentNode.CheckState!=CheckState.Unchecked) { DataRowView drv = treeList1.GetDataRecordByNode(parentNode) as DataRowView; if (drv != null) { string KeyFieldName = (string)drv["KeyFieldName"]; if (!lstCheckedKeyID.Contains(KeyFieldName)) { lstCheckedKeyID.Add(KeyFieldName); } } } foreach (TreeListNode node in parentNode.Nodes) { if (node.CheckState != CheckState.Unchecked) { DataRowView drv = treeList1.GetDataRecordByNode(node) as DataRowView;//关键代码,就是不知道是这样获取数据而纠结了很久(鬼知道可以转换为DataRowView啊) if (drv != null) { string KeyFieldName = (string)drv["KeyFieldName"]; lstCheckedKeyID.Add(KeyFieldName); } } GetCheckedKeyID(node); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37