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>

属性说明:

背景及前景颜色变化
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容