一、前言
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