DevExpress.XtraTreeList.TreeList + Winform + Access2013 使用實例(一)
在WinForm開發(fā)過程中使用到了第三方控件DevExpress中的TreeList,為了方便大家以及后面的查閱,特此將開發(fā)過程中的一些經(jīng)驗寫出來供大家參考,包括了TreeList的一些外觀現(xiàn)實,節(jié)點獲取,以及Access數(shù)據(jù)庫的批量存儲操作等。本文同時也參考了網(wǎng)上的一些資料,特此向大神們致敬!
TreeList的重要屬性
關(guān)于綁定數(shù)據(jù)的屬性
在TreeList中,綁定數(shù)據(jù)時有兩個重要的基本屬性:KeyFieldName,以及ParentFieldName。通過這兩個基本屬性的設(shè)置,即可實現(xiàn)層級結(jié)構(gòu)顯示。
在KeyFieldName以及ParentFieldName中分別綁定相應(yīng)的數(shù)據(jù)表字段名
數(shù)據(jù)庫設(shè)計及其數(shù)據(jù)如下圖:
綁定數(shù)據(jù)庫的操作方法在后面再詳細(xì)講解。
關(guān)于顯示CheckBox的屬性
只需要設(shè)置OptionsView.ShowCheckBoxes = True
即可
關(guān)于Checkbox顯示3種選中狀態(tài)
需要設(shè)置OptionsBehavior.AllowIndeterminateCheckState = True
即可
關(guān)于如何顯示這三種選中狀態(tài),在后面詳細(xì)講解。
關(guān)于設(shè)置TreeList是否可編輯
有時候,我們并不希望在單擊TreeList單元格的時候,出現(xiàn)單元格可以編輯的情況,此時就需要設(shè)置TreeList的可編輯屬性了。設(shè)置方法為OptionsBehavior.Editable = False
。
顯示CheckBox的三種選中狀態(tài)
CheckBox的三種顯示狀態(tài)如下:
其具體代碼如下
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>
/// 設(shè)置子節(jié)點的狀態(tài)
/// </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>
/// 設(shè)置父節(jié)點的狀態(tài)
/// </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選中的節(jié)點
獲取方法如下:
private List<string> lstCheckedKeyID = new List<string>();//選擇KeyID集合
/// <summary>
/// 獲取選擇狀態(tài)的數(shù)據(jù)主鍵ID集合
/// </summary>
/// <param name="parentNode">父級節(jié)點</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;//關(guān)鍵代碼,就是不知道是這樣獲取數(shù)據(jù)而糾結(jié)了很久(鬼知道可以轉(zhuǎn)換為DataRowView啊)
if (drv != null)
{
string KeyFieldName = (string)drv["KeyFieldName"];
lstCheckedKeyID.Add(KeyFieldName);
}
}
GetCheckedKeyID(node);
}
}
/// <summary>
/// 獲取選中的節(jié)點
/// </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
當(dāng)需要獲取到當(dāng)前所選取的節(jié)點時,直接在相應(yīng)時間中調(diào)用findOrigin(treeList1);
即可。
當(dāng)時使用這個方法的時候發(fā)現(xiàn),獲取的節(jié)點并不全。比如說,當(dāng)前表中只有父節(jié)點,如在表中的俄羅斯,選中它,運(yùn)行上述代碼,并不能獲取到其KeyFieldName;再比方說,選中了南京之后,只能獲取到南京和江蘇省的KeyFieldName,并不能獲取到中國的KeyFieldName。
上述問題的解決方法之一
在獲取到節(jié)點之后,將其及與之對應(yīng)的層次結(jié)構(gòu)存進(jìn)數(shù)據(jù)表中。由于在上一段中獲取的節(jié)點并不全面,所以
我只能在另起爐灶獲取到所有應(yīng)該存儲的節(jié)點。
/// <summary>
/// 比較當(dāng)前Key與已經(jīng)存儲的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>
/// 獲取當(dāng)前集合中字符串長度的最大值
/// </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>
/// 找到當(dāng)前所有需要保存的節(jié)點
/// </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
通過以上方法可以獲得相應(yīng)的所有的KeyFieldName。
上述問題的解決方法之二
GetCheckedKeyID函數(shù)修改如下:
/// <summary>
/// 獲取選擇狀態(tài)的數(shù)據(jù)主鍵ID集合
/// </summary>
/// <param name="parentNode">父級節(jié)點</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;//關(guān)鍵代碼,就是不知道是這樣獲取數(shù)據(jù)而糾結(jié)了很久(鬼知道可以轉(zhuǎn)換為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