1.如何展開結點時改變圖標(注意:不是選中時)
要在目錄中使用圖標首先要加入一個控件ImageList(命名為imageList1),然后可以按圖片的index或名稱引用圖片.
然后需要在TreeView控件的ImageList屬性中指向imageList1.
TreeView有兩個屬性:
SelectImageIndex:選中該結點時顯示的圖片的索引
ImageIndex:未選中該結點時顯示的圖片的索引
可以實現的效果是,選中某個結點時該結點的圖片進行改變,如果我們的目標也是如此,萬事已經大吉了.
但我希望的效果是:展開某個結點時該結點的圖片改變(如顯示為打開的盒子),折疊時該結點的圖片改變(如包裝好的盒子).直接使用屬性無法實現該效果.
實現原理是:展開某個結點時將SelectImageIndex和ImageIndex統統指向打開盒子的圖片
折疊某個結點時將SelectImageIndex和ImageIndex統統指向包裝盒子的圖片
自然需要用到兩個事件:TreeView的AfterExpand和AfterCollapse事件
private void treeView1_AfterExpand(object sender, TreeViewEventArgs e) { e.Node.ImageIndex = 1; //指向展開的圖標 e.Node.SelectedImageIndex = 1;//指向展開的圖標 } private void treeView1_AfterCollapse(object sender, TreeViewEventArgs e) { e.Node.ImageIndex = 0; //指向關閉的圖標 e.Node.SelectedImageIndex = 0;//指向關閉的圖標 }
PS:當對某個結點的屬性
ImageIndex和SelectedImageIndex賦值后,向它添加的子結點如未指定該屬性,似乎會沿用父結點的屬性,所以通常我會對子結點單獨設置該值 .
2.重命名結點名稱
重命名結點的功能很好實現,只要將TreeView的LabelEdit屬性改為True即可.選中某個結點后再單擊(提示:間隔短的話算做雙擊),然后結點名稱變成可以編輯狀態,修改文本后即可完成.
但我的程序設計是這樣的:結點的名稱會在后面自動加入子結點的數量(注:樹的深度為2).
效果如圖:
這樣就會帶來麻煩(我們總是擅長給自己制造麻煩?),因為我在重命名的時候並不想在編輯狀態下名稱中包含后面數字(它只在顯示的時候出現).
假設我希望將"新建分組"重命名為"我的分組",我希望進入編輯狀態時,名稱為"新建分組",修改后的名稱為"我的分組",退出編輯狀態時顯示為"我的分組[1]".
那實際的邏輯就是這樣:
1.進入編輯狀態時將名稱的數字去掉
2.退出編輯狀態時將名稱加入數字.
so easy!
那如何獲取進入編輯狀態時的事件呢?我沒有找到,或者可能就沒有,但我們可以在結點的單擊事件中進行捕獲,再判斷結點的文本是否為選中狀態
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.IsSelected) { e.Node.Text = "替換掉數字,請自己實現"; } }
然后捕捉編輯結束事件,實現加數字的方法
private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) { if (!e.CancelEdit) { e.Node.Text=e.Label+string.Format(" [{0}]", e.Node.Nodes.Count.ToString());
e.CancelEdit = true; //注意這里
}
}
以下是重點:
在上面的代碼沒加入 e.CancelEdit = true 之前,會有一個奇怪的現象,當我將結點的名稱修改后不會出現后面的數字.假設我修改的順序是這樣:將A->B->B
很有趣的現象:當從A變成B時后面的數字不會出現,當從B變成B時(實際沒有發行變動),數字又出現了.跟蹤了很久的程序加上了很長的時間分析,終於明白原因了.
當我們修改結點的文本時是這樣的一個順序:結點進入編輯狀態->觸發BeforeLabelEdit事件->觸發AterLabelEdit事件->刷新界面用新值代替舊值.
在 treeView1_AfterLabelEdit事件的參數中有兩個屬性:s.Label 修改之后的值(新值,可能為null,只讀) 和s.Node.Text 修改之前的值(舊值,可讀寫).
仔細分析后可以理解上面的現象:當從A->修改為B時,我們的代碼對e.Node.Text(舊值)進行了賦值加入數字,最后程序刷新界面時會用新值代替舊值.這時我們加入的數字被新值Label覆蓋了(代碼做了無用功)
而我們從B->修改為B時,由於新值(Label)為null,則系統不會執行最后一步,所以我們添加的數字得到了保留.
最終的做法,就是將參數的e.CancelEdit改為true,告訴系統我們就當我們沒有編輯過吧.這樣系統就不會執行最后一步了,我們代碼的修改得到了保留.