WPF中改TabItem为图片按钮样式

1,835 阅读1分钟

为建立中文知识库加块砖        ——中科大胡不归

问题描述

WPF可以轻松通过Style实现自定义的控件样式,比如如下这种带高亮条选中效果的TabItem。

代码实例

1. Style定义

在App.xaml中定义TabItem的图片按钮样式。此处定义:TabItem在Normal态下显示Icon属性传入的图片资源,在选中时显示IconSelected传入的图片资源。【可选】在选中时修改TabItem的背景。

<Application.Resources>

        <Style TargetType="{x:Type local:MyTabItem}">
            <Setter Property="Foreground" Value="Black" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:MyTabItem}">
                        <!--  常态显示Icon -->
                        <Grid x:Name="Panel">
                            <Image x:Name="img2Off" Width="20" Height="20" Source="{TemplateBinding Icon}"   Margin="5" />
                        </Grid>
                        <ControlTemplate.Triggers>
                            <!--  选中时 -->
                            <Trigger Property="IsSelected" Value="True">
                                <Setter TargetName="Panel" Property="Background" Value="LightSkyBlue" />
                                <Setter TargetName="img2Off" Property="Source" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconSelected}" />
                            </Trigger>
                            <!--  非选中时 -->
                            <Trigger Property="IsSelected" Value="False">
                                <Setter TargetName="Panel" Property="Background" Value="White" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Application.Resources>

需要注意的是TemplateBinding只能用在ControlTemplate中,Setter中是没有此功能。Setter需要使用布局中传入的IconSelected属性,可以通过如下形式:Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconSelected}"

2. 自定义MyTabItem

因为需要用到xaml中传入的新的属性参数,所以我们需要继承TabItem实现自定义MyTabItem类。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApplication2
{
    public class MyTabItem : TabItem
    {
        static MyTabItem()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyTabItem), new FrameworkPropertyMetadata(typeof(MyTabItem)));
        }
        
        // 定义Icon属性
        public ImageSource Icon
        {
            get => (ImageSource) GetValue(IconProperty);
            set => SetValue(IconProperty, value);
        }

        public static readonly DependencyProperty IconProperty =
            DependencyProperty.Register("Icon", typeof(ImageSource), typeof(MyTabItem), new PropertyMetadata(null));
        
        // 定义IconSelected属性
        public ImageSource IconSelected
        {
            get => (ImageSource) GetValue(IconSelectedProperty);
            set => SetValue(IconSelectedProperty, value);
        }

        public static readonly DependencyProperty IconSelectedProperty =
            DependencyProperty.Register("IconSelected", typeof(ImageSource), typeof(MyTabItem), new PropertyMetadata(null));
    }
}

3. 控件引用

<Window x:Class="WpfApplication2.TabDemo"
        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:WpfApplication2"
        mc:Ignorable="d"
        Title="TabDemo" Height="450" Width="800">
    <Grid>
        <TabControl TabStripPlacement="Right" Height="{Binding ElementName=ParentPanel, Path=Height}"
                    Width="{Binding ElementName=ParentPanel, Path=Width}" >
            <local:MyTabItem x:Name="TabItem1" Icon="Resource/Image/studio.ico" IconSelected="Resource/Image/studio3.ico">
                <TextBlock>江山各有</TextBlock>
            </local:MyTabItem>
            <local:MyTabItem x:Name="TabItem2" Icon="Resource/Image/studio.ico" IconSelected="Resource/Image/studio3.ico">
                <TextBlock>风景无限</TextBlock>
            </local:MyTabItem>
        </TabControl>

    </Grid>
</Window>

4. 效果演示

参考文章

  1. 为WPF中TabControl的TabItem添加图片
  2. Can my WPF Style Setter use a TemplateBinding?
  3. WPF TabControl-设置TabItems的样式