• 【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和逻辑解耦。

  • 相关阅读:
    九度OJ 1333:考研海报 (区间操作)
    九度OJ 1326:Waiting in Line(排队) (模拟)
    九度OJ 1325:Battle Over Cities(城市间的战争) (并查集)
    九度OJ 1324:The Best Rank(最优排名) (排序)
    九度OJ 1323:World Cup Betting(世界杯) (基础题)
    九度OJ 1283:第一个只出现一次的字符 (计数)
    九度OJ 1262:Sequence Construction puzzles(I)_构造全递增序列 (DP)
    九度OJ 1261:寻找峰值点 (基础题)
    SDWebImage
    MBProgressHUDDemo
  • 原文地址:https://www.cnblogs.com/RMay/p/1273927.html
Copyright © 2020-2023  润新知