【WPF】一个类似于QQ面板的GroupShelf控件

最近做控件上了瘾,现在把做的一个类似于QQ面板的控件放上来。

 

  

【分析】

从整体来看,这个控件应该同ListBox,ListView这类控件一样,是一个ItemsControl,而中间的项,就是它的Item。

因此,为了完成一个这样的控件,至少需要两个东西:

GroupShelf:也就是充当容器角色的控件

GroupShelfItem:即这个控件中的项

 

其中,GroupShelf需要保证某项的展开同时,其他项被折叠。而GroupShelfItem需要提供Header和Content,同时,需要能支持展开的空能。

 

【控件的实现】

 

GroupShelfItem

 

首先,我们从GroupShelfItem入手,因为它比较单纯,在HeaderedContentControl的基础上提供展开,收缩功能即可:

 

Code

 

默认的Style

 

Code

 

 

GroupShelfItem提供了一个Command来操作它的展开和收缩。同时,在Expand的时候通知GroupShelf处理。在默认的控件模板中通过按钮来触发这个Command。

 

GroupShelfPanel

 

    GroupShelf的主要工作就是维护GroupShelfItem展开和收缩时的状态处理。但是,按照WPF的方式,这个布局的工作不应该由它来完成,而是由我们提供一个ItemsPanel给它。所以,在GroupShelf之前,GroupShelfPanel应运而生。

 

    写一个Panel最重要的工作就是重载MeasureOverride和ArrangeOverride两个方法。分析GroupShelfPanel的行为,其实是“指定的孩子填充剩余空间”。就系统提供的Panel来说,DockPanel跟它的行为是最接近的,因为DockPanel提供了LastChildFill的行为。既然如此,我们就打开Reflector,从DockPanel里面“借”点代码过来用用:

 

Code

 

    当然,改动还是比较大的。主要的改动集中在ArrangeOverride上。排列的逻辑应该是:把“要填充的孩子”之前的元素从上到下排列,把“要填充的孩子”之后的元素从下往上排列。剩余的空间都留给这个“要填充的孩子”。而对于MeasureOverride,我们要做的就是去掉DockPanel里面对于Left和Right的判断。(当然,如果考虑到以后要提供两种布局的方向:Horizontal和Vertical的话,还是需要保留一下的)

 

GroupShelf

 

    上面两个都完成后,GroupShelf的工作就很简单了。它就是在Item的Expand发生变化时,通知别的Item Collapse,然后通知GroupPanel去重新布局。

 

 

Code

 

一个需要注意的地方是它的模板:

 

Code

 

    我放置了一个GroupPanel,并且指定了它是ItemsHost,而不是放置ItemsPresenter。这一点是比较重要的,因为只有当ItemsPanel是GroupPanel的时候,才能够有指定孩子填充的效果,因此这个GroupPanel需要是TemplatePart。如果修改了这个模板,换成别的Panel,比如StackPanel,则行为会有所不同。

 

【使用该控件】

   

这个控件的使用是非常简单的:

 

Code

 

代码下载https://files.cnblogs.com/RMay/AccordianDemo.rar

注:我用的是.Net 3.5 Sp1,如果是3.0-3.5请删除模板中的ContentStringFormat相关的东西

 

修正一下:

在GroupShelf的模板中,直接写

<local:GroupShelfPanel IsItemsHost="True" ChildToFill="{TemplateBinding ExpandedItem}"/>

即可,而在GroupShelf中的相关字段和方法都可以删除,UI和逻辑解耦。

posted @ 2008-08-22 11:50  大佛脚下  阅读(7887)  评论(21编辑  收藏  举报