WPF ComboBox+TabControl自定义样式实现

WPF涉及到很多自定义样式的实现,以下是我实现的ComboBox+TabControl控件相结合的自定义样式,实现效果如下:

未做选择时
做完选择后


选择“标志”
选择“处理”

实现步骤:

(1)考虑到可以在多个地方使用该控件,创建一个通用的UserControl来实现该控件;

<UserControl x:Class="Teacher.UserControls.Common.ComboxTabControl"

            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

            xmlns:local="clr-namespace:Teacher.UserControls.Common"

            mc:Ignorable="d" DataContextChanged="UserControl_DataContextChanged" >

<Grid>

        <ComboBox Name="ComboxBtn"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="#EBEFF5" Background="#f9fafc"  ItemsSource="{Binding Path=ComboxList}" DropDownClosed="ComboxBtn_DropDownClosed"  SelectedIndex="0"  >          

        </ComboBox>       

    </Grid>

</UserControl>

属性说明如下:

属性说明1

(2)重写ComboBox的样式

<UserControl.Resources>

<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">

            <Setter Property="Template">

                <Setter.Value>

                    <ControlTemplate TargetType="ComboBox">

                        <Grid>

                            <ToggleButton FontSize="{TemplateBinding FontSize}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" MinWidth="60" MinHeight="30" Foreground="#666666" Content="{Binding DisplayVaule}"  Style="{StaticResource ComboBoxToggleButton}" x:Name="ToggleButton" Focusable="false" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>

                            <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True"  PopupAnimation="Slide">

                                <Border  Name="DropDown"  SnapsToDevicePixels="True"               

                            Width="{TemplateBinding ActualWidth}" MaxHeight="300">

                                    <Border.Effect>

                                        <DropShadowEffect BlurRadius="14" ShadowDepth="4.5" Direction="270" Color="#000000" Opacity=".1" RenderingBias="Performance"/>

                                    </Border.Effect>

                                    <TabControl Name="SelfTabControl" Style="{StaticResource TabControlStyle}">                  

<!--TabControl内容后面会补充说明 -->               

                                    </TabControl>

                                </Border>

                            </Popup>

                        </Grid>

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

    </UserControl.Resources>

属性说明如下:

\ast 通过自定义的Style来实现特殊样式

自定义ComboBox样式

\ast 下拉列表按钮开关,点击时要呼出下拉选项;

其中Content处的内容绑定的是最终要展现的值;Style处是ToggleButton自定义风格样式;

IsChecked则和Popup里的IsOpen的值双向绑定,在点击时,呼出Popup,再次点击则关闭Popup;

ToggleButton

\ast ToggleButton风格实现

<Style x:Key="ComboBoxToggleButton" TargetType="ToggleButton" >

        <Setter Property="Template">

            <Setter.Value>

                <ControlTemplate TargetType="ToggleButton">

                    <Border Background="{TemplateBinding Background}" BorderThickness="1" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="2">

                        <Grid Width="{Binding}" VerticalAlignment="Center" Cursor="Hand" >

                            <Grid.ColumnDefinitions>

                                <ColumnDefinition Width="15"/>

                                <ColumnDefinition Width="*"/>

                                <ColumnDefinition Width="40"/>

                            </Grid.ColumnDefinitions>

                            <ContentPresenter Grid.Column="1" HorizontalAlignment="Left" TextBlock.FontSize="{TemplateBinding FontSize}" TextBlock.Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" ContentSource="{Binding}"  />

                            <Image HorizontalAlignment="Center" Grid.Column="2" Width="12" Height="12" Source="/Resource/image/exam/三角箭头上.png" Name="icon"  Cursor="Hand" RenderTransformOrigin="0.5,0.5">

                                <Image.RenderTransform>

                                    <RotateTransform x:Name="rotateTransform"  />

                                </Image.RenderTransform>

                            </Image>

                        </Grid>

                    </Border>

                    <ControlTemplate.Triggers>

                        <Trigger  Property="IsChecked"  Value="False" >

                            <Setter  Property="LayoutTransform" TargetName="icon">

                                <Setter.Value>

                                    <RotateTransform Angle="180"/>

                                </Setter.Value>

                            </Setter>

                        </Trigger>

                    </ControlTemplate.Triggers>

                </ControlTemplate>

            </Setter.Value>

        </Setter>

    </Style>

属性说明:

样式说明
触发条件后,箭头图标旋转180度

(3)接下来是重头戏:TabControl的自定义样式实现

<TabControl Name="SelfTabControl" Style="{StaticResource TabControlStyle}">

<!--TabItem内容后面会补充说明 -->        

</TabControl>

TabControlStyle实现如下:

<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">

            <Setter Property="HorizontalContentAlignment" Value="Center"/>

            <Setter Property="VerticalContentAlignment" Value="Center"/>

            <Setter Property="Background" Value="White"/>

            <Setter Property="BorderBrush" Value="#FFECECEC"/>

            <Setter Property="BorderThickness" Value="1,0,1,1"/>

            <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>

                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,0,1,0" >

                                <UniformGrid  x:Name="headerPanel" Rows="1" Background="Transparent" Grid.Column="0" IsItemsHost="true"  Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>

                            </Border>

                            <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" ContentSource="SelectedContent" Margin="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

                            </Border>

                        </Grid>                     

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

属性说明:

BorderThickness定义边框样式,UniformGrid用于实现具有相同宽度的TabItem

(4)依然是实现重点:TabControl下增加两个TabItem项,Header分别是“标志”、“处理”,因“标志”、“处理”两处的TabItem实现除数据源不同外,其他基本一致,所以后面以“标志”项作为例子讲解;

<TabControl Name="SelfTabControl" Style="{StaticResource TabControlStyle}">

        <TabItem Header="标志" IsSelected="{Binding Path=ShowFlagTab}" Style="{StaticResource TabItemStyle}">

               <ItemsControl  Width="{TemplateBinding ActualWidth}" ItemsSource="{Binding Path=FlagList}"  HorizontalAlignment="Left" BorderThickness="0" >

                     <ItemsControl.ItemsPanel>

                            <ItemsPanelTemplate>

                                    <StackPanel />

                             </ItemsPanelTemplate>

                       </ItemsControl.ItemsPanel>

                      <ItemsControl.ItemTemplate>

                             <DataTemplate>

                                  <MenuItem x:Name="btnFlag" Height="34" Background="Transparent" VerticalAlignment="Center" IsCheckable="True" IsChecked="{Binding IsChecked}" Click="BtnFlag_Click" >

                                        <MenuItem.Template>

                                              <ControlTemplate TargetType="{x:Type MenuItem}">

                                                      <Border x:Name="border" Width="{TemplateBinding ActualWidth}" Height="34"  Background="Transparent" BorderBrush="#FFECECEC" CornerRadius="0" BorderThickness="0" SnapsToDevicePixels="True" VerticalAlignment="Center">

                                                        <WrapPanel VerticalAlignment="Center">

                                                               <RadioButton Visibility="Collapsed" x:Name="rdo" IsChecked="{Binding IsChecked,RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}" GroupName="A" IsThreeState="False"/>

                                                               <TextBlock x:Name="txt" Margin="20,0" Foreground="#5A646E" FontSize="14" Text="{Binding Path=Name}" VerticalAlignment="Center" ></TextBlock>

                                                          </WrapPanel>

                                                   </Border>

                                     <ControlTemplate.Triggers>

                                         <Trigger Property="IsMouseOver" Value="true">

                                                <Setter TargetName="border" Property="Background" Value="#F4F6FD"></Setter>

                                         </Trigger>

                                         <Trigger Property="IsChecked" SourceName="rdo" Value="true">

                         <Setter TargetName="txt" Property="Foreground" Value="#00C18A"></Setter>

                         <Setter Property="IsChecked" Value="true"></Setter>

                                         </Trigger>

                                     </ControlTemplate.Triggers>

                                  </ControlTemplate>

                                 </MenuItem.Template>

                                </MenuItem>                                                         

                              </DataTemplate>

                           </ItemsControl.ItemTemplate>                                                   

                         </ItemsControl>                                           

               </TabItem>

<TabItem Header="处理" IsSelected="{Binding Path=ShowHandleTab}" Style="{StaticResource TabItemStyle}">

   <ItemsControl Width="{TemplateBinding ActualWidth}"  ItemsSource="{Binding Path=HandleList}"  HorizontalAlignment="Left" BorderThickness="0" >

        <ItemsControl.ItemsPanel>

              <ItemsPanelTemplate>

                    <StackPanel/>

              </ItemsPanelTemplate>

         </ItemsControl.ItemsPanel>

         <ItemsControl.ItemTemplate>

                 <DataTemplate>                                                           

                     <MenuItem x:Name="btnHandle" Height="34" Background="Transparent" VerticalAlignment="Center" IsCheckable="True" IsChecked="{Binding IsChecked}" Click="BtnHandle_Click" >

                      <MenuItem.Template>

                           <ControlTemplate TargetType="{x:Type MenuItem}">

                                 <Border x:Name="border" Width="{TemplateBinding ActualWidth}" Height="34" Background="Transparent" BorderBrush="#FFECECEC" CornerRadius="0" BorderThickness="0" SnapsToDevicePixels="True">

                                       <WrapPanel VerticalAlignment="Center">

                                             <RadioButton Visibility="Collapsed" x:Name="rdo" IsChecked="{Binding IsChecked,RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}" GroupName="B" IsThreeState="False"/>

                                             <TextBlock x:Name="txt" Margin="20,0" Foreground="#5A646E" FontSize="14" Text="{Binding Path=Name}" VerticalAlignment="Center" ></TextBlock>

                                        </WrapPanel>

                                 </Border>

          <ControlTemplate.Triggers>

               <Trigger Property="IsMouseOver" Value="true">

                  <Setter TargetName="border" Property="Background" Value="#F4F6FD"></Setter>

                </Trigger>

                <Trigger Property="IsChecked" SourceName="rdo" Value="true">

                   <Setter TargetName="txt" Property="Foreground" Value="#00C18A"></Setter>

                   <Setter Property="IsChecked" Value="true"></Setter>

                </Trigger>                                                                         

          </ControlTemplate.Triggers>

         </ControlTemplate>

        </MenuItem.Template>

       </MenuItem>

      </DataTemplate>

     </ItemsControl.ItemTemplate>

    </ItemsControl>

   </TabItem>

</TabControl>

属性说明:

重点属性截图

标记1:IsSelected用于记录上次的选中项的值

标记2:TabItemStyle在后面补充说明

标记3:ItemsControl的数据源绑定

标记4:IsChecked用于记忆上次选中项

标记5:Click用于点击下拉选项的值后,触发后续处理事件

标记6:RadioButton的IsCheck和标记4绑定的是同一个值,用于在下拉选项选中后,触发标记9事件;

标记7:Text绑定的是数据源Name属性的值;

标记8: hover样式设置;

标记9:若RadioButton被选中则触发TextBlock前景颜色变化;

(5)TabItemStyle样式实现

<Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}">

            <Setter Property="Height" Value="30"/>

            <Setter Property="FontSize" Value="12"/> 

            <Setter Property="HorizontalContentAlignment" Value="Center"/>

            <Setter Property="VerticalContentAlignment" Value="Center"/>

            <Setter Property="Template">

                <Setter.Value>

                    <ControlTemplate TargetType="{x:Type TabItem}">

                        <Border x:Name="templateRoot" SnapsToDevicePixels="True" Background="Transparent" >

                            <TextBlock x:Name="txt" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Header}" TextTrimming="CharacterEllipsis" />

                        </Border>

                        <ControlTemplate.Triggers>                         

                            <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="Foreground" TargetName="txt" Value="#999999"/>

                                <Setter Property="Background" TargetName="templateRoot" Value="#F0F1F6"/>

                            </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="Foreground" TargetName="txt" Value="#666666"/>

                                <Setter Property="Background" TargetName="templateRoot" Value="White"/>

                            </MultiDataTrigger>

                            <MultiDataTrigger>

                                <MultiDataTrigger.Conditions>

                                    <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="false"/>

                                    <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/>

                                </MultiDataTrigger.Conditions>

                                <Setter Property="Foreground" TargetName="txt" Value="#999999"/>

                                <Setter Property="Background" TargetName="templateRoot" Value="#F0F1F6"/>

                            </MultiDataTrigger>

                        </ControlTemplate.Triggers>

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

属性说明:

背景及前景颜色变化
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容