好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WPF自定义TreeView控件样式实现QQ联系人列表效果

一、前言

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分层模板样式代码

?

<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样式代码

?

<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样式代码

?

<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、转换器代码

?

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、引用示例

?

<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、初始化数据源及绑定对象

?

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://HdhCmsTestcnblogs测试数据/xiaomingg/p/8765802.html

dy("nrwz");

查看更多关于WPF自定义TreeView控件样式实现QQ联系人列表效果的详细内容...

  阅读:48次