一、前言
treeview这个控件对于我来说是用得比较多的,以前做的小聊天软件(好友列表)、音乐播放器(播放列表)、类库展示器(树形类结构)等都用的是treeview,普通的treeview并不能满足我们的需求。因此我们需要滴对treeview进行改造。下面的内容将介绍仿qq联系人treeview样式及treeview数据绑定方法。
二、treeview仿qq联系人列表
准确的说不是仿qq联系人列表,这个treeview样式作为组织架构来使用更好。废话不多说,先看效果:
2.1、基本思路
像这种联系人列表一般涉及到多层级数据,而且有很多数据是需要动态更新的,如果通过手动一条条增加数据反而更复杂,而且不方便。因此为了绑定数据方便我们使用分层模板hierarchicaldatatemplate。
分层模板中存在两种样式,一种是分组样式,一种是人员样式。不管是分组还是人员绑定的都是对象,这样我们在对象中添加一个属性来辨别是否为分组-isgrouping。
默认的treeview控件四周会有边距,因此需要设置下treeview的样式。另外鼠标经过和鼠标选中的背景色需要变化,因此还需要设置treeviewitem的样式。
根据思路,我们需要设置三个样式,treeview样式,treeviewitem样式,hierarchicaldatatemplate分层模板样式。另外为了自动计算下一级的边距,我们需要添加一个转换器indentconverter。还需要一个转换器需要将布尔类型的isgrouping转换为visibility,还需要一个转换器来对visibility取反。
这样三个样式,三个转换器。就可以实现我们上面的效果,另外还可以进行动态数据绑定。
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、转换器代码
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、初始化数据源及绑定对象
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= "未分组联系人(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 ; } } |
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:http://www.cnblogs.com/xiaomingg/p/8765802.html