当前位置: 移动技术网 > IT编程>开发语言>.net > WPF中Expander的用法和控件模板详解

WPF中Expander的用法和控件模板详解

2019年09月09日  | 移动技术网IT编程  | 我要评论

中国专利查询系统,圣元汇力多,亚锦赛乒乓球2017

一、expander的用法

  在wpf中,expander是一个很实用的复合控件,可以很方便的实现下拉菜单和导航栏等功能。先介绍简单的用法,而后分析他的控件模板。

<window.resources>
        <resourcedictionary>
            <style x:key="expander.stackpanel.style" targettype="frameworkelement">
                <setter property="maxwidth" value="80"></setter>
                <setter property="minwidth" value="50"></setter>
                <setter property="horizontalalignment" value="left"></setter>
            </style>
        </resourcedictionary>
    </window.resources>
    <grid>
        
        <expander style="{dynamicresource expanderstyle}" header="头部">
            <stackpanel>
                <button style="{staticresource expander.stackpanel.style}">内容1</button>
                <radiobutton style="{staticresource expander.stackpanel.style}">内容2</radiobutton>
                <textbox style="{staticresource expander.stackpanel.style}">内容3</textbox>
                <textblock style="{staticresource expander.stackpanel.style}">内容4</textblock>
            </stackpanel>
        </expander>
    </grid>

可以看到expander主要分为头部和内容两部分,展开时才显示内容,而内容部分可以存放丰富的内容

效果图:

二、控件模板

  如何获取控件本身默认的控件模板请看我的另一篇文章:

  因为控件模板比较复杂,先看大概的构成:

 

再看看主样式部分(expandersytle)的构成:

 

再看向下展开时头部的样式构成:

 

如下为我标注了注释的完整控件模板代码:

<solidcolorbrush x:key="expander.mouseover.circle.stroke" color="#ff5593ff"/>
            <solidcolorbrush x:key="expander.mouseover.circle.fill" color="#fff3f9ff"/>
            <solidcolorbrush x:key="expander.mouseover.arrow.stroke" color="#ff000000"/>
            <solidcolorbrush x:key="expander.pressed.circle.stroke" color="#ff3c77dd"/>
            <solidcolorbrush x:key="expander.pressed.circle.fill" color="#ffd9ecff"/>
            <solidcolorbrush x:key="expander.pressed.arrow.stroke" color="#ff000000"/>
            <solidcolorbrush x:key="expander.disabled.circle.stroke" color="#ffbcbcbc"/>
            <solidcolorbrush x:key="expander.disabled.circle.fill" color="#ffe6e6e6"/>
            <solidcolorbrush x:key="expander.disabled.arrow.stroke" color="#ff707070"/>
            <solidcolorbrush x:key="expander.static.circle.fill" color="#ffffffff"/>
            <solidcolorbrush x:key="expander.static.circle.stroke" color="#ff333333"/>
            <solidcolorbrush x:key="expander.static.arrow.stroke" color="#ff333333"/>
            <!--expanddirection=right,即向右展开时的头部样式-->
            <style x:key="expanderrightheaderstyle" targettype="{x:type togglebutton}">
                <setter property="template">
                    <setter.value>
                        <controltemplate targettype="{x:type togglebutton}">
                            <border padding="{templatebinding padding}">
                                <grid background="transparent" snapstodevicepixels="false">
                                    <grid.rowdefinitions>
                                        <rowdefinition height="19"/>
                                        <rowdefinition height="*"/>
                                    </grid.rowdefinitions>
                                    <grid>
                                        <grid.layouttransform>
                                            <transformgroup>
                                                <transformgroup.children>
                                                    <transformcollection>
                                                        <rotatetransform angle="-90"/>
                                                    </transformcollection>
                                                </transformgroup.children>
                                            </transformgroup>
                                        </grid.layouttransform>
                                        <ellipse x:name="circle" fill="yellow" horizontalalignment="center" height="19" stroke="yellow" verticalalignment="center" width="19"/>
                                        <path x:name="arrow" data="m 1,1.5 l 4.5,5 l 8,1.5" horizontalalignment="center" snapstodevicepixels="false" stroke="{staticresource expander.static.arrow.stroke}" strokethickness="2" verticalalignment="center"/>
                                    </grid>
                                    <contentpresenter horizontalalignment="center" margin="0,4,0,0" grid.row="1" recognizesaccesskey="true" snapstodevicepixels="true" verticalalignment="top"/>
                                </grid>
                            </border>
                            <controltemplate.triggers>
                                <trigger property="ischecked" value="true">
                                    <setter property="data" targetname="arrow" value="m 1,4.5  l 4.5,1  l 8,4.5"/>
                                </trigger>
                                <trigger property="ismouseover" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.mouseover.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.mouseover.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.mouseover.arrow.stroke}"/>
                                </trigger>
                                <trigger property="ispressed" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.pressed.circle.stroke}"/>
                                    <setter property="strokethickness" targetname="circle" value="1.5"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.pressed.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.pressed.arrow.stroke}"/>
                                </trigger>
                                <trigger property="isenabled" value="false">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.disabled.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.disabled.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.disabled.arrow.stroke}"/>
                                </trigger>
                            </controltemplate.triggers>
                        </controltemplate>
                    </setter.value>
                </setter>
            </style>
            <!--expanddirection=up,即向上展开时的头部样式-->
            <style x:key="expanderupheaderstyle" targettype="{x:type togglebutton}">
                <setter property="template">
                    <setter.value>
                        <controltemplate targettype="{x:type togglebutton}">
                            <border padding="{templatebinding padding}">
                                <grid background="transparent" snapstodevicepixels="false">
                                    <grid.columndefinitions>
                                        <columndefinition width="19"/>
                                        <columndefinition width="*"/>
                                    </grid.columndefinitions>
                                    <grid>
                                        <grid.layouttransform>
                                            <transformgroup>
                                                <transformgroup.children>
                                                    <transformcollection>
                                                        <rotatetransform angle="180"/>
                                                    </transformcollection>
                                                </transformgroup.children>
                                            </transformgroup>
                                        </grid.layouttransform>
                                        <ellipse x:name="circle" fill="{staticresource expander.static.circle.fill}" horizontalalignment="center" height="19" stroke="{staticresource expander.static.circle.stroke}" verticalalignment="center" width="19"/>
                                        <path x:name="arrow" data="m 1,1.5 l 4.5,5 l 8,1.5" horizontalalignment="center" snapstodevicepixels="false" stroke="{staticresource expander.static.arrow.stroke}" strokethickness="2" verticalalignment="center"/>
                                    </grid>
                                    <contentpresenter grid.column="1" horizontalalignment="left" margin="4,0,0,0" recognizesaccesskey="true" snapstodevicepixels="true" verticalalignment="center"/>
                                </grid>
                            </border>
                            <controltemplate.triggers>
                                <trigger property="ischecked" value="true">
                                    <setter property="data" targetname="arrow" value="m 1,4.5  l 4.5,1  l 8,4.5"/>
                                </trigger>
                                <trigger property="ismouseover" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.mouseover.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.mouseover.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.mouseover.arrow.stroke}"/>
                                </trigger>
                                <trigger property="ispressed" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.pressed.circle.stroke}"/>
                                    <setter property="strokethickness" targetname="circle" value="1.5"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.pressed.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.pressed.arrow.stroke}"/>
                                </trigger>
                                <trigger property="isenabled" value="false">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.disabled.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.disabled.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.disabled.arrow.stroke}"/>
                                </trigger>
                            </controltemplate.triggers>
                        </controltemplate>
                    </setter.value>
                </setter>
            </style>
            <!--expanddirection=left,即向左展开时的头部样式-->
            <style x:key="expanderleftheaderstyle" targettype="{x:type togglebutton}">
                <setter property="template">
                    <setter.value>
                        <controltemplate targettype="{x:type togglebutton}">
                            <border padding="{templatebinding padding}">
                                <grid background="transparent" snapstodevicepixels="false">
                                    <grid.rowdefinitions>
                                        <rowdefinition height="19"/>
                                        <rowdefinition height="*"/>
                                    </grid.rowdefinitions>
                                    <grid>
                                        <grid.layouttransform>
                                            <transformgroup>
                                                <transformgroup.children>
                                                    <transformcollection>
                                                        <rotatetransform angle="90"/>
                                                    </transformcollection>
                                                </transformgroup.children>
                                            </transformgroup>
                                        </grid.layouttransform>
                                        <ellipse x:name="circle" fill="{staticresource expander.static.circle.fill}" horizontalalignment="center" height="19" stroke="{staticresource expander.static.circle.stroke}" verticalalignment="center" width="19"/>
                                        <path x:name="arrow" data="m 1,1.5 l 4.5,5 l 8,1.5" horizontalalignment="center" snapstodevicepixels="false" stroke="{staticresource expander.static.arrow.stroke}" strokethickness="2" verticalalignment="center"/>
                                    </grid>
                                    <contentpresenter horizontalalignment="center" margin="0,4,0,0" grid.row="1" recognizesaccesskey="true" snapstodevicepixels="true" verticalalignment="top"/>
                                </grid>
                            </border>
                            <controltemplate.triggers>
                                <trigger property="ischecked" value="true">
                                    <setter property="data" targetname="arrow" value="m 1,4.5  l 4.5,1  l 8,4.5"/>
                                </trigger>
                                <trigger property="ismouseover" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.mouseover.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.mouseover.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.mouseover.arrow.stroke}"/>
                                </trigger>
                                <trigger property="ispressed" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.pressed.circle.stroke}"/>
                                    <setter property="strokethickness" targetname="circle" value="1.5"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.pressed.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.pressed.arrow.stroke}"/>
                                </trigger>
                                <trigger property="isenabled" value="false">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.disabled.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.disabled.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.disabled.arrow.stroke}"/>
                                </trigger>
                            </controltemplate.triggers>
                        </controltemplate>
                    </setter.value>
                </setter>
            </style>
            <!--expanddirection=down,即向下展开时的头部样式(一般默认向下展开)-->
            <style x:key="expanderdownheaderstyle" targettype="{x:type togglebutton}">
                <setter property="template">
                    <setter.value>
                        <controltemplate targettype="{x:type togglebutton}">
                            <border padding="{templatebinding padding}">
                                <grid background="transparent" snapstodevicepixels="false">
                                    <grid.columndefinitions>
                                        <columndefinition width="19"/>
                                        <columndefinition width="*"/>   <!--可变部分自适应存放文字-->
                                    </grid.columndefinitions>
                                    <!--下拉头部(ellipse和path组成圆圈箭头图标 contentpresenter为文字)-->
                                    <ellipse x:name="circle" fill="{staticresource expander.static.circle.fill}" horizontalalignment="center" height="19" stroke="{staticresource expander.static.circle.stroke}" verticalalignment="center" width="19"/>
                                    <path x:name="arrow" data="m 1,1.5 l 4.5,5 l 8,1.5" horizontalalignment="center" snapstodevicepixels="false" stroke="{staticresource expander.static.arrow.stroke}" strokethickness="2" verticalalignment="center"/>
                                    <contentpresenter grid.column="1" horizontalalignment="left" margin="4,0,0,0" recognizesaccesskey="true" snapstodevicepixels="true" verticalalignment="center"/>
                                </grid>
                            </border>
                            <controltemplate.triggers>
                                <!--选中时向下箭头变为为向上箭头-->
                                <trigger property="ischecked" value="true">
                                    <setter property="data" targetname="arrow" value="m 1,4.5  l 4.5,1  l 8,4.5"/>
                                </trigger>
                                <trigger property="ismouseover" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.mouseover.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.mouseover.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.mouseover.arrow.stroke}"/>
                                </trigger>
                                <trigger property="ispressed" value="true">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.pressed.circle.stroke}"/>
                                    <setter property="strokethickness" targetname="circle" value="1.5"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.pressed.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.pressed.arrow.stroke}"/>
                                </trigger>
                                <trigger property="isenabled" value="false">
                                    <setter property="stroke" targetname="circle" value="{staticresource expander.disabled.circle.stroke}"/>
                                    <setter property="fill" targetname="circle" value="{staticresource expander.disabled.circle.fill}"/>
                                    <setter property="stroke" targetname="arrow" value="{staticresource expander.disabled.arrow.stroke}"/>
                                </trigger>
                            </controltemplate.triggers>
                        </controltemplate>
                    </setter.value>
                </setter>
            </style>
            <!--键盘焦点样式-->
            <style x:key="expanderheaderfocusvisual">
                <setter property="control.template">
                    <setter.value>
                        <controltemplate>
                            <border>
                                <rectangle margin="0" snapstodevicepixels="true" stroke="black" strokethickness="1" strokedasharray="1 2"/>
                            </border>
                        </controltemplate>
                    </setter.value>
                </setter>
            </style>
            <!--expander样式-->
            <style x:key="expanderstyle" targettype="{x:type expander}">
                <setter property="foreground" value="{dynamicresource {x:static systemcolors.controltextbrushkey}}"/>
                <setter property="background" value="transparent"/>
                <setter property="horizontalcontentalignment" value="stretch"/>
                <setter property="verticalcontentalignment" value="stretch"/>
                <setter property="borderbrush" value="transparent"/>
                <setter property="borderthickness" value="1"/>
                <setter property="template">
                    <setter.value>
                        <!--控件模板-->
                        <controltemplate targettype="{x:type expander}">
                            <border borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}" background="{templatebinding background}" cornerradius="3" snapstodevicepixels="true">
                                <dockpanel>
                                    <!--头部标题-->
                                    <togglebutton x:name="headersite" contenttemplate="{templatebinding headertemplate}" contenttemplateselector="{templatebinding headertemplateselector}" content="{templatebinding header}" dockpanel.dock="top" foreground="{templatebinding foreground}" fontweight="{templatebinding fontweight}" focusvisualstyle="{staticresource expanderheaderfocusvisual}" fontstyle="{templatebinding fontstyle}" fontstretch="{templatebinding fontstretch}" fontsize="{templatebinding fontsize}" fontfamily="{templatebinding fontfamily}" horizontalcontentalignment="{templatebinding horizontalcontentalignment}" ischecked="{binding isexpanded, mode=twoway, relativesource={relativesource templatedparent}}" margin="1" minwidth="0" minheight="0" padding="{templatebinding padding}" style="{staticresource expanderdownheaderstyle}" verticalcontentalignment="{templatebinding verticalcontentalignment}"/>
                                    <!--下拉内容-->
                                    <contentpresenter x:name="expandsite" dockpanel.dock="bottom" focusable="false" horizontalalignment="{templatebinding horizontalcontentalignment}" margin="{templatebinding padding}" visibility="collapsed" verticalalignment="{templatebinding verticalcontentalignment}"/>
                                </dockpanel>
                            </border>
                            <!--触发器-->
                            <controltemplate.triggers>
                                <!--内容展开则显示隐藏内容-->
                                <trigger property="isexpanded" value="true">
                                    <setter property="visibility" targetname="expandsite" value="visible"/>
                                </trigger>
                                <!--向左、右、上展开修改dockpanel中标题和内容布局方式实现-->
                                <trigger property="expanddirection" value="right">
                                    <setter property="dockpanel.dock" targetname="expandsite" value="right"/>
                                    <setter property="dockpanel.dock" targetname="headersite" value="left"/>
                                    <setter property="style" targetname="headersite" value="{staticresource expanderrightheaderstyle}"/>
                                </trigger>
                                <trigger property="expanddirection" value="up">
                                    <setter property="dockpanel.dock" targetname="expandsite" value="top"/>
                                    <setter property="dockpanel.dock" targetname="headersite" value="bottom"/>
                                    <setter property="style" targetname="headersite" value="{staticresource expanderupheaderstyle}"/>
                                </trigger>
                                <trigger property="expanddirection" value="left">
                                    <setter property="dockpanel.dock" targetname="expandsite" value="left"/>
                                    <setter property="dockpanel.dock" targetname="headersite" value="right"/>
                                    <setter property="style" targetname="headersite" value="{staticresource expanderleftheaderstyle}"/>
                                </trigger>
                                <trigger property="isenabled" value="false">
                                    <setter property="foreground" value="{dynamicresource {x:static systemcolors.graytextbrushkey}}"/>
                                </trigger>
                            </controltemplate.triggers>
                        </controltemplate>
                    </setter.value>
                </setter>
            </style>

 

  知道了expander默认控件模板的构成就可以根据需要修改,轻松构建自定义的导航栏等功能(建议只修改需要修改的部分)。

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网