一、前言
treeview這個(gè)控件對(duì)于我來(lái)說(shuō)是用得比較多的,以前做的小聊天軟件(好友列表)、音樂(lè)播放器(播放列表)、類庫(kù)展示器(樹形類結(jié)構(gòu))等都用的是treeview,普通的treeview并不能滿足我們的需求。因此我們需要滴對(duì)treeview進(jìn)行改造。下面的內(nèi)容將介紹仿qq聯(lián)系人treeview樣式及treeview數(shù)據(jù)綁定方法。
二、treeview仿qq聯(lián)系人列表
準(zhǔn)確的說(shuō)不是仿qq聯(lián)系人列表,這個(gè)treeview樣式作為組織架構(gòu)來(lái)使用更好。廢話不多說(shuō),先看效果:
2.1、基本思路
像這種聯(lián)系人列表一般涉及到多層級(jí)數(shù)據(jù),而且有很多數(shù)據(jù)是需要?jiǎng)討B(tài)更新的,如果通過(guò)手動(dòng)一條條增加數(shù)據(jù)反而更復(fù)雜,而且不方便。因此為了綁定數(shù)據(jù)方便我們使用分層模板hierarchicaldatatemplate。
分層模板中存在兩種樣式,一種是分組樣式,一種是人員樣式。不管是分組還是人員綁定的都是對(duì)象,這樣我們?cè)趯?duì)象中添加一個(gè)屬性來(lái)辨別是否為分組-isgrouping。
默認(rèn)的treeview控件四周會(huì)有邊距,因此需要設(shè)置下treeview的樣式。另外鼠標(biāo)經(jīng)過(guò)和鼠標(biāo)選中的背景色需要變化,因此還需要設(shè)置treeviewitem的樣式。
根據(jù)思路,我們需要設(shè)置三個(gè)樣式,treeview樣式,treeviewitem樣式,hierarchicaldatatemplate分層模板樣式。另外為了自動(dòng)計(jì)算下一級(jí)的邊距,我們需要添加一個(gè)轉(zhuǎn)換器indentconverter。還需要一個(gè)轉(zhuǎn)換器需要將布爾類型的isgrouping轉(zhuǎn)換為visibility,還需要一個(gè)轉(zhuǎn)換器來(lái)對(duì)visibility取反。
這樣三個(gè)樣式,三個(gè)轉(zhuǎn)換器。就可以實(shí)現(xiàn)我們上面的效果,另外還可以進(jìn)行動(dòng)態(tài)數(shù)據(jù)綁定。
2.2、樣式代碼
hierarchicaldatatemplate分層模板樣式代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<hierarchicaldatatemplate x:key= "itemnode" itemssource= "{binding children,mode=twoway}" > <grid background= "transparent" > <grid.resources> <convert:booltovisible x:key= "booltovisible" /> <convert:visibletoreverse x:key= "visibletoreverse" /> </grid.resources> <grid minheight= "30" x:name= "userinfo" background= "transparent" margin= "-5 0 0 0" visibility= "{binding visibility,elementname=groupinginfo,converter={staticresource visibletoreverse}}" > <grid height= "50" x:name= "grid" > <border background= "#62acf9" width= "40" height= "40" cornerradius= "4" horizontalalignment= "left" margin= "0 0 0 0" > <textblock text= "{binding surname}" fontsize= "23" foreground= "white" verticalalignment= "center" horizontalalignment= "center" /> </border> <textblock text= "{binding name}" margin= "50 7 0 0" fontsize= "13" /> <textblock text= "{binding info}" foreground= "#808080" margin= "50 30 0 0" /> <textblock text= "{binding count,stringformat={}{0}人}" foreground= "#808080" horizontalalignment= "right" verticalalignment= "center" margin= "0 0 5 0" /> </grid> </grid> <stackpanel minheight= "25" x:name= "groupinginfo" orientation= "horizontal" background= "transparent" horizontalalignment= "left" visibility= "{binding isgrouping,converter={staticresource booltovisible}}" > <textblock text= "{binding displayname}" margin= "3 0" verticalalignment= "center" horizontalalignment= "left" /> </stackpanel> </grid> </hierarchicaldatatemplate> |
treeviewitem樣式代碼
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
<style x:key= "defaulttreeviewitem" targettype= "{x:type treeviewitem}" > <setter property= "minheight" value= "25" /> <setter property= "background" value= "transparent" /> <setter property= "snapstodevicepixels" value= "true" /> <setter property= "margin" value= "0" /> <setter property= "template" > <setter.value> <controltemplate targettype= "{x:type treeviewitem}" > <controltemplate.resources> <convert:indentconverter x:key= "indentconverter" /> </controltemplate.resources> <grid background= "transparent" > <grid.rowdefinitions> <rowdefinition/> <rowdefinition/> </grid.rowdefinitions> <border name= "itembackground" background= "{templatebinding background}" borderbrush= "{templatebinding borderbrush}" borderthickness= "{templatebinding borderthickness}" padding= "{templatebinding padding}" > <grid background= "transparent" > <grid x:name= "itemroot" margin= "{binding converter={staticresource indentconverter},relativesource={relativesource templatedparent}}" background= "transparent" > <grid.columndefinitions> <columndefinition width= "16" /> <columndefinition width= "*" /> </grid.columndefinitions> <togglebutton x:name= "expander" horizontalalignment= "left" clickmode= "press" ischecked= "{binding isexpanded, relativesource={relativesource templatedparent}}" > <togglebutton.style> <style targettype= "{x:type togglebutton}" > <setter property= "focusable" value= "false" /> <setter property= "width" value= "16" /> <setter property= "height" value= "16" /> <setter property= "template" > <setter.value> <controltemplate targettype= "{x:type togglebutton}" > <border background= "transparent" height= "16" padding= "5" width= "16" > <path x:name= "expandpath" data= "m0,0 l0,6 l6,0 z" fill= "#66645e" stroke= "#66645e" > <path.rendertransform> <rotatetransform angle= "135" centery= "3" centerx= "3" /> </path.rendertransform> </path> </border> <controltemplate.triggers> <trigger property= "ischecked" value= "true" > <setter property= "rendertransform" targetname= "expandpath" > <setter.value> <rotatetransform angle= "180" centery= "3" centerx= "3" /> </setter.value> </setter> <setter property= "fill" targetname= "expandpath" value= "#66645e" /> <setter property= "stroke" targetname= "expandpath" value= "#66645e" /> </trigger> <trigger property= "ismouseover" value= "true" > <setter property= "stroke" targetname= "expandpath" value= "#66645e" /> <setter property= "fill" targetname= "expandpath" value= "#66645e" /> </trigger> <multitrigger> <multitrigger.conditions> <condition property= "ismouseover" value= "true" /> <condition property= "ischecked" value= "true" /> </multitrigger.conditions> <setter property= "stroke" targetname= "expandpath" value= "#66645e" /> <setter property= "fill" targetname= "expandpath" value= "#66645e" /> </multitrigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> </togglebutton.style> </togglebutton> <contentpresenter grid.column= "1" x:name= "part_header" contentsource= "header" horizontalalignment= "stretch" > </contentpresenter> </grid> </grid> </border> <itemspresenter x:name= "itemshost" grid.row= "1" /> </grid> <controltemplate.triggers> <datatrigger binding= "{binding isgrouping}" value= "false" > <setter property= "visibility" targetname= "expander" value= "hidden" /> </datatrigger> <trigger property= "hasitems" value= "false" > <setter property= "visibility" targetname= "expander" value= "collapsed" /> </trigger> <trigger property= "isexpanded" value= "false" > <setter property= "visibility" targetname= "itemshost" value= "collapsed" /> </trigger> <trigger property= "isselected" value= "true" > <setter property= "background" targetname= "itembackground" value= "#fae388" /> </trigger> <multitrigger> <multitrigger.conditions> <condition property= "isfocused" value= "false" /> <condition sourcename= "itembackground" property= "ismouseover" value= "true" /> </multitrigger.conditions> <setter property= "background" value= " #fceeb9" targetname= "itembackground" /> </multitrigger> <trigger property= "isenabled" value= "false" > <setter property= "foreground" value= "{dynamicresource {x:static systemcolors.graytextbrushkey}}" /> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> |
treeview樣式代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<style x:key= "defaulttreeview" targettype= "{x:type treeview}" > <setter property= "scrollviewer.cancontentscroll" value= "true" /> <setter property= "virtualizingstackpanel.isvirtualizing" value= "true" ></setter> <setter property= "virtualizingstackpanel.virtualizationmode" value= "recycling" /> <setter property= "scrollviewer.isdeferredscrollingenabled" value= "false" /> <setter property= "itemcontainerstyle" value= "{staticresource defaulttreeviewitem}" ></setter> <setter property= "padding" value= "0" /> <setter property= "itemspanel" > <setter.value> <itemspaneltemplate> <virtualizingstackpanel isitemshost= "true" margin= "0" /> </itemspaneltemplate> </setter.value> </setter> </style> |
2.3、轉(zhuǎn)換器代碼
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
|
public class indentconverter : ivalueconverter { public object convert( object value, type targettype, object parameter, cultureinfo culture) { double colunwidth = 10; double left = 0.0; uielement element = value as treeviewitem; while (element.gettype() != typeof (treeview)) { element = (uielement)visualtreehelper.getparent(element); if (element.gettype() == typeof (treeviewitem)) left += colunwidth; } return new thickness(left, 0, 0, 0); } public object convertback( object value, type targettype, object parameter, cultureinfo culture) { throw new notimplementedexception(); } } public class booltovisible : ivalueconverter { public object convert( object value, type targettype, object parameter, cultureinfo culture) { if (( bool )value) return visibility.visible; else return visibility.collapsed; } public object convertback( object value, type targettype, object parameter, cultureinfo culture) { throw new notimplementedexception(); } } public class visibletoreverse : ivalueconverter { public object convert( object value, type targettype, object parameter, cultureinfo culture) { if ((visibility)value == visibility.visible) return visibility.collapsed; else return visibility.visible; } public object convertback( object value, type targettype, object parameter, cultureinfo culture) { throw new notimplementedexception(); } } |
2.4、引用示例
1
2
|
<treeview x:name= "treevieworg" borderthickness= "1" borderbrush= "#bbb" background= "transparent" width= "280" height= "500" margin= "10" itemtemplate= "{staticresource itemnode}" style= "{staticresource defaulttreeview}" > </treeview> |
2.5、初始化數(shù)據(jù)源及綁定對(duì)象
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
|
public mainwindow() { initializecomponent(); orglist = new observablecollection<orgmodel>() { new orgmodel() { isgrouping= true , displayname= "單位名稱(3/7)" , children= new observablecollection<orgmodel>() { new orgmodel(){ isgrouping= true , displayname= "未分組聯(lián)系人(2/4)" , children= new observablecollection<orgmodel>() { new orgmodel(){ isgrouping= false , surname= "劉" , name= "劉棒" , info= "我要走向天空!" , count=3 } } } }, } }; treevieworg.itemssource = orglist; } public observablecollection<orgmodel> orglist { get ; set ; } public class orgmodel { public bool isgrouping { get ; set ; } public observablecollection<orgmodel> children { get ; set ; } public string displayname { get ; set ; } public string surname { get ; set ; } public string name { get ; set ; } public string info { get ; set ; } public int count { get ; set ; } } |
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。
原文鏈接:http://www.cnblogs.com/xiaomingg/p/8765802.html