一、前言
程序中经常会用到tabcontrol控件,默认的控件样式很普通。而且样式或功能不一定符合我们的要求。比如:我们需要tabcontrol的标题能够居中、或平均分布;或者我们希望tabcontrol的标题能够进行关闭。要实现这些功能我们需要对tabcontrol的样式进行定义。
二、实现tabcontrol的标题平均分布
默认的tabcontrol标题是使用tabpanel容器包含的。要想实现tabcontrol标题头平均分布,需要把tabpanel替换成uniformgrid;
替换后的tabcontrol样式如下:
<style x:key= "tabcontrolstyle" targettype= "{x:type tabcontrol}" >
<setter property= "padding" value= "2" />
<setter property= "horizontalcontentalignment" value= "center" />
<setter property= "verticalcontentalignment" value= "center" />
<setter property= "background" value= "white" />
<setter property= "borderbrush" value= "#ffacacac" />
<setter property= "borderthickness" value= "1" />
<setter property= "foreground" value= "{dynamicresource {x:static systemcolors.controltextbrushkey}}" />
<setter property= "template" >
<setter.value>
<controltemplate targettype= "{x:type tabcontrol}" >
<grid x:name= "templateroot" cliptobounds= "true" snapstodevicepixels= "true" keyboardnavigation.tabnavigation= "local" >
<grid.columndefinitions>
<columndefinition x:name= "columndefinition0" />
<columndefinition x:name= "columndefinition1" width= "0" />
</grid.columndefinitions>
<grid.rowdefinitions>
<rowdefinition x:name= "rowdefinition0" height= "auto" />
<rowdefinition x:name= "rowdefinition1" height= "*" />
</grid.rowdefinitions>
<uniformgrid x:name= "headerpanel" rows= "1" background= "transparent" grid.column= "0" isitemshost= "true" margin= "0" grid.row= "0" keyboardnavigation.tabindex= "1" panel.zindex= "1" />
<line x1= "0" x2= "{binding actualwidth, relativesource={relativesource self}}" stroke= "white" strokethickness= "0.1" verticalalignment= "bottom" margin= "0 0 0 1" snapstodevicepixels= "true" />
<border x:name= "contentpanel" borderbrush= "{templatebinding borderbrush}" borderthickness= "{templatebinding borderthickness}" background= "{templatebinding background}" grid.column= "0" keyboardnavigation.directionalnavigation= "contained" grid.row= "1" keyboardnavigation.tabindex= "2" keyboardnavigation.tabnavigation= "local" >
<contentpresenter x:name= "part_selectedcontenthost" contenttemplate= "{templatebinding selectedcontenttemplate}" content= "{templatebinding selectedcontent}" contentstringformat= "{templatebinding selectedcontentstringformat}" contentsource= "selectedcontent" margin= "0" snapstodevicepixels= "{templatebinding snapstodevicepixels}" />
</border>
</grid>
<controltemplate.triggers>
<trigger property= "tabstripplacement" value= "bottom" >
<setter property= "grid.row" targetname= "headerpanel" value= "1" />
<setter property= "grid.row" targetname= "contentpanel" value= "0" />
<setter property= "height" targetname= "rowdefinition0" value= "*" />
<setter property= "height" targetname= "rowdefinition1" value= "auto" />
</trigger>
<trigger property= "tabstripplacement" value= "left" >
<setter property= "grid.row" targetname= "headerpanel" value= "0" />
<setter property= "grid.row" targetname= "contentpanel" value= "0" />
<setter property= "grid.column" targetname= "headerpanel" value= "0" />
<setter property= "grid.column" targetname= "contentpanel" value= "1" />
<setter property= "width" targetname= "columndefinition0" value= "auto" />
<setter property= "width" targetname= "columndefinition1" value= "*" />
<setter property= "height" targetname= "rowdefinition0" value= "*" />
<setter property= "height" targetname= "rowdefinition1" value= "0" />
</trigger>
<trigger property= "tabstripplacement" value= "right" >
<setter property= "grid.row" targetname= "headerpanel" value= "0" />
<setter property= "grid.row" targetname= "contentpanel" value= "0" />
<setter property= "grid.column" targetname= "headerpanel" value= "1" />
<setter property= "grid.column" targetname= "contentpanel" value= "0" />
<setter property= "width" targetname= "columndefinition0" value= "*" />
<setter property= "width" targetname= "columndefinition1" value= "auto" />
<setter property= "height" targetname= "rowdefinition0" value= "*" />
<setter property= "height" targetname= "rowdefinition1" value= "0" />
</trigger>
<trigger property= "isenabled" value= "false" >
<setter property= "textelement.foreground" targetname= "templateroot" value= "{dynamicresource {x:static systemcolors.graytextbrushkey}}" />
</trigger>
</controltemplate.triggers>
</controltemplate>
</setter.value>
</setter>
</style>
即使这样设置了,tabcontrol的标题还是很丑,这个时候就需要通过设置tabitem来更改标题样式了。
tabitem样式如下:
<style x:key= "tabitemstyle" targettype= "{x:type tabitem}" >
<setter property= "foreground" value= "white" />
<setter property= "background" value= "transparent" />
<setter property= "borderbrush" value= "#ffacacac" />
<setter property= "margin" value= "0" />
<setter property= "horizontalcontentalignment" value= "stretch" />
<setter property= "verticalcontentalignment" value= "stretch" />
<setter property= "template" >
<setter.value>
<controltemplate targettype= "{x:type tabitem}" >
<grid x:name= "templateroot" snapstodevicepixels= "true" background= "transparent" >
<textblock x:name= "txt" visibility= "visible" verticalalignment= "center" horizontalalignment= "center" text= "{templatebinding header}" tooltip= "{templatebinding header}" foreground= "{templatebinding foreground}" texttrimming= "characterellipsis" />
</grid>
<controltemplate.triggers>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding ismouseover, relativesource={relativesource self}}" value= "true" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "top" />
</multidatatrigger.conditions>
<setter property= "foreground" targetname= "txt" value= "#fffea1" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "left" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "bottom" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "right" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "top" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isselected, relativesource={relativesource self}}" value= "true" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "top" />
</multidatatrigger.conditions>
<setter property= "panel.zindex" value= "1" />
<setter property= "foreground" targetname= "txt" value= "#fffea1" />
</multidatatrigger>
</controltemplate.triggers>
</controltemplate>
</setter.value>
</setter>
</style>
至此,样式已经设置完毕,引用示例:
<grid background= "#858586" >
<tabcontrol style= "{staticresource tabcontrolstyle}" width= "300" height= "200" background= "transparent" borderbrush= "transparent" borderthickness= "0" >
<tabitem style= "{staticresource tabitemstyle}" cursor= "hand" header= "音乐电台" height= "38" >
<grid background= "#33ffffff" >
<textblock text= "音乐电台" verticalalignment= "center" horizontalalignment= "center" />
</grid>
</tabitem>
<tabitem style= "{staticresource tabitemstyle}" cursor= "hand" header= "mv电台" height= "38" >
<grid background= "#33ffffff" >
<textblock text= "mv电台" verticalalignment= "center" horizontalalignment= "center" />
</grid>
</tabitem>
</tabcontrol>
</grid>
效果如下:
三、实现tabcontrol标题居中显示(不平均分布)
同理需要更改tabcontrol的样式和tabitem的样式。需要把使用tabpanel作为标题的容器,设置horizontalalignment为center;
tabcontrol的样式如下:
<style x:key= "tabcontrolwithunderlinestyle" targettype= "{x:type tabcontrol}" >
<setter property= "padding" value= "2" />
<setter property= "horizontalcontentalignment" value= "center" />
<setter property= "verticalcontentalignment" value= "center" />
<setter property= "background" value= "white" />
<setter property= "borderbrush" value= "#ffacacac" />
<setter property= "borderthickness" value= "1" />
<setter property= "foreground" value= "{dynamicresource {x:static systemcolors.controltextbrushkey}}" />
<setter property= "template" >
<setter.value>
<controltemplate targettype= "{x:type tabcontrol}" >
<grid x:name= "templateroot" cliptobounds= "true" snapstodevicepixels= "true" keyboardnavigation.tabnavigation= "local" >
<grid.columndefinitions>
<columndefinition x:name= "columndefinition0" />
<columndefinition x:name= "columndefinition1" width= "0" />
</grid.columndefinitions>
<grid.rowdefinitions>
<rowdefinition x:name= "rowdefinition0" height= "auto" />
<rowdefinition x:name= "rowdefinition1" height= "*" />
</grid.rowdefinitions>
<tabpanel x:name= "headerpanel" horizontalalignment= "center" background= "transparent" grid.column= "0" isitemshost= "true" margin= "0" grid.row= "0" keyboardnavigation.tabindex= "1" panel.zindex= "1" />
<line x1= "0" x2= "{binding actualwidth, relativesource={relativesource self}}" stroke= "gray" strokethickness= "0.1" verticalalignment= "bottom" margin= "0 0 0 1" snapstodevicepixels= "true" />
<border x:name= "contentpanel" borderbrush= "{templatebinding borderbrush}" borderthickness= "{templatebinding borderthickness}" background= "{templatebinding background}" grid.column= "0" keyboardnavigation.directionalnavigation= "contained" grid.row= "1" keyboardnavigation.tabindex= "2" keyboardnavigation.tabnavigation= "local" >
<contentpresenter x:name= "part_selectedcontenthost" contenttemplate= "{templatebinding selectedcontenttemplate}" content= "{templatebinding selectedcontent}" contentstringformat= "{templatebinding selectedcontentstringformat}" contentsource= "selectedcontent" margin= "0" snapstodevicepixels= "{templatebinding snapstodevicepixels}" />
</border>
</grid>
<controltemplate.triggers>
<trigger property= "tabstripplacement" value= "bottom" >
<setter property= "grid.row" targetname= "headerpanel" value= "1" />
<setter property= "grid.row" targetname= "contentpanel" value= "0" />
<setter property= "height" targetname= "rowdefinition0" value= "*" />
<setter property= "height" targetname= "rowdefinition1" value= "auto" />
</trigger>
<trigger property= "tabstripplacement" value= "left" >
<setter property= "grid.row" targetname= "headerpanel" value= "0" />
<setter property= "grid.row" targetname= "contentpanel" value= "0" />
<setter property= "grid.column" targetname= "headerpanel" value= "0" />
<setter property= "grid.column" targetname= "contentpanel" value= "1" />
<setter property= "width" targetname= "columndefinition0" value= "auto" />
<setter property= "width" targetname= "columndefinition1" value= "*" />
<setter property= "height" targetname= "rowdefinition0" value= "*" />
<setter property= "height" targetname= "rowdefinition1" value= "0" />
</trigger>
<trigger property= "tabstripplacement" value= "right" >
<setter property= "grid.row" targetname= "headerpanel" value= "0" />
<setter property= "grid.row" targetname= "contentpanel" value= "0" />
<setter property= "grid.column" targetname= "headerpanel" value= "1" />
<setter property= "grid.column" targetname= "contentpanel" value= "0" />
<setter property= "width" targetname= "columndefinition0" value= "*" />
<setter property= "width" targetname= "columndefinition1" value= "auto" />
<setter property= "height" targetname= "rowdefinition0" value= "*" />
<setter property= "height" targetname= "rowdefinition1" value= "0" />
</trigger>
<trigger property= "isenabled" value= "false" >
<setter property= "textelement.foreground" targetname= "templateroot" value= "{dynamicresource {x:static systemcolors.graytextbrushkey}}" />
</trigger>
</controltemplate.triggers>
</controltemplate>
</setter.value>
</setter>
</style>
tabitem样式如下:
<style x:key= "tabitemexwithunderlinestyle" targettype= "{x:type tabitem}" >
<setter property= "foreground" value= "white" />
<setter property= "background" value= "transparent" />
<setter property= "borderbrush" value= "#ffacacac" />
<setter property= "margin" value= "0" />
<setter property= "horizontalcontentalignment" value= "stretch" />
<setter property= "verticalcontentalignment" value= "stretch" />
<setter property= "template" >
<setter.value>
<controltemplate targettype= "{x:type tabitem}" >
<grid x:name= "templateroot" snapstodevicepixels= "true" background= "transparent" >
<border x:name= "_underline" borderbrush= "#37aefe" borderthickness= "0" margin= "{templatebinding margin}" />
<grid>
<textblock x:name= "txt" visibility= "visible" verticalalignment= "center" horizontalalignment= "center" text= "{templatebinding header}" tooltip= "{templatebinding header}" foreground= "{templatebinding foreground}" texttrimming= "characterellipsis" />
</grid>
</grid>
<controltemplate.triggers>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding ismouseover, relativesource={relativesource self}}" value= "true" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "top" />
</multidatatrigger.conditions>
<setter property= "foreground" targetname= "txt" value= "#37aefe" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "left" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "bottom" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "right" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isenabled, relativesource={relativesource self}}" value= "false" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "top" />
</multidatatrigger.conditions>
<setter property= "opacity" targetname= "templateroot" value= "0.56" />
</multidatatrigger>
<multidatatrigger>
<multidatatrigger.conditions>
<condition binding= "{binding isselected, relativesource={relativesource self}}" value= "true" />
<condition binding= "{binding tabstripplacement, relativesource={relativesource findancestor, ancestorlevel=1, ancestortype={x:type tabcontrol}}}" value= "top" /> </multidatatrigger.conditions>
<setter property= "panel.zindex" value= "1" />
<setter property= "foreground" targetname= "txt" value= "#37aefe" />
<setter property= "borderthickness" targetname= "_underline" value= "0 0 0 2" />
</multidatatrigger>
</controltemplate.triggers>
</controltemplate>
</setter.value>
</setter>
</style>
引用示例:
<grid background= "#858586" >
<tabcontrol style= "{staticresource tabcontrolwithunderlinestyle}" foreground= "black" width= "300" height= "200" background= "transparent" borderbrush= "transparent" borderthickness= "0" >
<tabitem style= "{staticresource tabitemexwithunderlinestyle}" cursor= "hand" header= "音乐电台" height= "38" width= "70" margin= "5 0" >
<grid background= "#33ffffff" >
<textblock text= "音乐电台" verticalalignment= "center" horizontalalignment= "center" />
</grid>
</tabitem>
<tabitem style= "{staticresource tabitemexwithunderlinestyle}" cursor= "hand" header= "mv电台" height= "38" width= "70" margin= "5 0" >
<grid background= "#33ffffff" >
<textblock text= "mv电台" verticalalignment= "center" horizontalalignment= "center" />
</grid>
</tabitem>
</tabcontrol>
</grid>
效果如下:
四、带关闭按钮的tabcontrol
带关闭按钮的tabcontrol其实就是就是扩展tabitem,需要新建wpf自定义控件,命名为tabitemclose吧;
c#代码如下:
public class tabitemclose : tabitem
{
static tabitemclose()
{
defaultstylekeyproperty.overridemetadata( typeof (tabitemclose), new frameworkpropertymetadata( typeof (tabitemclose)));
}
private static void onpropertychanged(dependencyobject d, dependencypropertychangedeventargs e)
{
d.setvalue(e.property, e.newvalue);
}
/// <summary>
/// 是否可以关闭
/// </summary>
public bool iscanclose
{
get { return ( bool )getvalue(iscancloseproperty); }
set { setvalue(iscancloseproperty, value); }
}
public static readonly dependencyproperty iscancloseproperty =
dependencyproperty.register( "iscanclose" , typeof ( bool ), typeof (tabitemclose), new propertymetadata( true , onpropertychanged));
/// <summary>
/// 关闭的图标
/// </summary>
public imagesource closeicon
{
get { return (imagesource)getvalue(closeiconproperty); }
set { setvalue(closeiconproperty, value); }
}
public static readonly dependencyproperty closeiconproperty =
dependencyproperty.register( "closeicon" , typeof (imagesource), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 正常背景色
/// </summary>
public solidcolorbrush normalbackground
{
get { return (solidcolorbrush)getvalue(normalbackgroundproperty); }
set { setvalue(normalbackgroundproperty, value); }
}
public static readonly dependencyproperty normalbackgroundproperty =
dependencyproperty.register( "normalbackground" , typeof (solidcolorbrush), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 悬浮背景色
/// </summary>
public solidcolorbrush overbackgound
{
get { return (solidcolorbrush)getvalue(overbackgoundproperty); }
set { setvalue(overbackgoundproperty, value); }
}
public static readonly dependencyproperty overbackgoundproperty =
dependencyproperty.register( "overbackgound" , typeof (solidcolorbrush), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 选中背景色
/// </summary>
public solidcolorbrush selectedbackgound
{
get { return (solidcolorbrush)getvalue(selectedbackgoundproperty); }
set { setvalue(selectedbackgoundproperty, value); }
}
public static readonly dependencyproperty selectedbackgoundproperty =
dependencyproperty.register( "selectedbackgound" , typeof (solidcolorbrush), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 默认前景色
/// </summary>
public solidcolorbrush normalforeground
{
get { return (solidcolorbrush)getvalue(normalforegroundproperty); }
set { setvalue(normalforegroundproperty, value); }
}
public static readonly dependencyproperty normalforegroundproperty =
dependencyproperty.register( "normalforeground" , typeof (solidcolorbrush), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 悬浮前景色
/// </summary>
public solidcolorbrush overforeground
{
get { return (solidcolorbrush)getvalue(overforegroundproperty); }
set { setvalue(overforegroundproperty, value); }
}
public static readonly dependencyproperty overforegroundproperty =
dependencyproperty.register( "overforeground" , typeof (solidcolorbrush), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 选中前景色
/// </summary>
public solidcolorbrush selectedforeground
{
get { return (solidcolorbrush)getvalue(selectedforegroundproperty); }
set { setvalue(selectedforegroundproperty, value); }
}
public static readonly dependencyproperty selectedforegroundproperty =
dependencyproperty.register( "selectedforeground" , typeof (solidcolorbrush), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 控件圆角
/// </summary>
public cornerradius cornerradius
{
get { return (cornerradius)getvalue(cornerradiusproperty); }
set { setvalue(cornerradiusproperty, value); }
}
public static readonly dependencyproperty cornerradiusproperty =
dependencyproperty.register( "cornerradius" , typeof (cornerradius), typeof (tabitemclose), new propertymetadata( new cornerradius(0), onpropertychanged));
/// <summary>
/// 前置logo
/// </summary>
public imagesource logoicon
{
get { return (imagesource)getvalue(logoiconproperty); }
set { setvalue(logoiconproperty, value); }
}
public static readonly dependencyproperty logoiconproperty =
dependencyproperty.register( "logoicon" , typeof (imagesource), typeof (tabitemclose), new propertymetadata( null , onpropertychanged));
/// <summary>
/// 前置logo宽度
/// </summary>
public double logoiconwidth
{
get { return ( double )getvalue(logoiconwidthproperty); }
set { setvalue(logoiconwidthproperty, value); }
}
public static readonly dependencyproperty logoiconwidthproperty =
dependencyproperty.register( "logoiconwidth" , typeof ( double ), typeof (tabitemclose), new propertymetadata( double .parse( "0" ), onpropertychanged));
/// <summary>
/// 前置logo高度
/// </summary>
public double logoiconheigth
{
get { return ( double )getvalue(logoiconheigthproperty); }
set { setvalue(logoiconheigthproperty, value); }
}
public static readonly dependencyproperty logoiconheigthproperty =
dependencyproperty.register( "logoiconheigth" , typeof ( double ), typeof (tabitemclose), new propertymetadata( double .parse( "0" ), onpropertychanged));
/// <summary>
/// logopadding
/// </summary>
public thickness logopadding
{
get { return (thickness)getvalue(logopaddingproperty); }
set { setvalue(logopaddingproperty, value); }
}
public static readonly dependencyproperty logopaddingproperty =
dependencyproperty.register( "logopadding" , typeof (thickness), typeof (tabitemclose), new propertymetadata( new thickness(0), onpropertychanged));
/// <summary>
/// 关闭item事件
/// </summary>
public event routedeventhandler closeitem
{
add { addhandler(closeitemevent, value); }
remove { removehandler(closeitemevent, value); }
}
public static readonly routedevent closeitemevent =
eventmanager.registerroutedevent( "closeitem" , routingstrategy.bubble, typeof (routedeventhandler), typeof (tabitemclose));
/// <summary>
/// 关闭项的右键菜单
/// </summary>
public contextmenu itemcontextmenu { get ; set ; }
border itemborder;
public override void onapplytemplate()
{
base .onapplytemplate();
itemborder = template.findname( "_bordertop" , this ) as border;
if (itemcontextmenu != null )
{
itemborder.contextmenu = itemcontextmenu;
}
}
}
这里面我们添加了很多扩展功能,包括右键菜单,图标显示和控件圆角,以及各种背景色属性。
然后为tabitemclose设置样式
<style targettype= "{x:type local:tabitemclose}" >
<setter property= "horizontalcontentalignment" value= "stretch" />
<setter property= "verticalcontentalignment" value= "stretch" />
<setter property= "foreground" value= "#666666" />
<setter property= "margin" value= "0 0 0 0" />
<setter property= "padding" value= "0" />
<setter property= "borderthickness" value= "0" />
<setter property= "closeicon" value= "/images/close2.png" />
<setter property= "normalbackground" value= "white" />
<setter property= "overbackgound" value= "#33ca5100" />
<setter property= "selectedbackgound" value= "#ca5100" />
<setter property= "normalforeground" value= "#555558" />
<setter property= "overforeground" value= "white" />
<setter property= "selectedforeground" value= "white" />
<setter property= "template" >
<setter.value>
<controltemplate targettype= "{x:type local:tabitemclose}" >
<border x:name= "_bordertop" width= "{templatebinding width}" maxwidth= "{templatebinding maxwidth}" height= "{templatebinding height}" cornerradius= "{templatebinding cornerradius}" background= "{templatebinding normalbackground}" borderthickness= "{templatebinding borderthickness}" borderbrush= "{templatebinding borderbrush}" tooltip= "{templatebinding header}" >
<dockpanel>
<image x:name= "_logo" dockpanel.dock= "left" visibility= "visible" margin= "{templatebinding logopadding}" source= "{templatebinding logoicon}" verticalalignment= "center" horizontalalignment= "center" stretch= "uniform" width= "{templatebinding logoiconwidth}" height= "{templatebinding logoiconheigth}" />
<grid name= "_grid" snapstodevicepixels= "true" >
<grid.columndefinitions>
<columndefinition width= "*" />
<columndefinition x:name= "_col_close" width= "20" />
</grid.columndefinitions>
<border grid.columnspan= "2" background= "white" opacity= "0" />
<textblock x:name= "_txt" verticalalignment= "center" texttrimming= "characterellipsis" margin= "3 0 3 0" foreground= "{templatebinding normalforeground}" textalignment= "center" horizontalalignment= "center" text= "{templatebinding header}" />
<grid x:name= "_gridclose" grid.column= "1" >
<border x:name= "_borderbg" background= "black" opacity= "0" />
<local:buttonex x:name= "part_close_tabitem" horizontalalignment= "center" verticalalignment= "center" background= "transparent" visibility= "visible" icon= "{templatebinding closeicon}" buttontype= "icon" />
</grid>
</grid>
</dockpanel>
</border>
<controltemplate.triggers>
<trigger property= "logoicon" value= "{x:null}" >
<setter targetname= "_logo" property= "visibility" value= "collapsed" />
</trigger>
<trigger property= "iscanclose" value= "false" >
<setter targetname= "_gridclose" property= "visibility" value= "collapsed" />
<setter targetname= "_col_close" property= "width" value= "0" />
</trigger>
<trigger property= "isselected" value= "true" >
<setter targetname= "_bordertop" property= "background" value= "{binding selectedbackgound,relativesource={relativesource templatedparent}}" />
<setter targetname= "_txt" property= "foreground" value= "{binding selectedforeground,relativesource={relativesource templatedparent}}" />
</trigger>
<multitrigger>
<multitrigger.conditions>
<condition property= "ismouseover" value= "true" />
<condition property= "isselected" value= "false" />
</multitrigger.conditions>
<setter targetname= "_txt" property= "foreground" value= "{binding overforeground,relativesource={relativesource templatedparent}}" />
<setter targetname= "_bordertop" property= "background" value= "{binding overbackgound,relativesource={relativesource templatedparent}}" />
</multitrigger>
</controltemplate.triggers>
</controltemplate>
</setter.value>
</setter>
</style>
这里面使用了一个close的图标
tabcontrol的图标可设置可不设置,看自己需要。
这里面还用到了前面讲的控件buttonex,定义方法我就不重复赘述了。大家可以通过这个链接跳转查看: http://HdhCmsTestzzvips测试数据/article/226264.html 。buttonex.cs里面还要添加几个方法用来支持关闭tabitem:
protected override void onclick()
{
base .onclick();
if (! string .isnullorempty(name) && name == "part_close_tabitem" )
{
tabitemclose itemclose = findvisualparent<tabitemclose>( this );
(itemclose.parent as tabcontrol).items.remove(itemclose);
routedeventargs args = new routedeventargs(tabitemclose.closeitemevent, itemclose);
itemclose.raiseevent(args);
}
}
public static t findvisualparent<t>(dependencyobject obj) where t : class
{
while (obj != null )
{
if (obj is t)
return obj as t;
obj = visualtreehelper.getparent(obj);
}
return null ;
}
引用示例:
<grid background= "#858586" >
<tabcontrol foreground= "black" width= "300" height= "200" background= "transparent" borderbrush= "transparent" borderthickness= "0" >
<local:tabitemclose cursor= "hand" header= "音乐电台" height= "20" width= "100" >
<grid background= "#aaffffff" >
<textblock text= "音乐电台" verticalalignment= "center" horizontalalignment= "center" />
</grid>
</local:tabitemclose>
<local:tabitemclose cursor= "hand" header= "mv电台" height= "20" width= "100" >
<grid background= "#aaffffff" >
<textblock text= "mv电台" verticalalignment= "center" horizontalalignment= "center" />
</grid>
</local:tabitemclose>
</tabcontrol>
</grid>
效果如下:
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:http://HdhCmsTestcnblogs测试数据/xiaomingg/p/8870825.html
dy("nrwz");
查看更多关于WPF如何自定义TabControl控件样式示例详解的详细内容...