WPF如何实现一个漂亮的页签导航UI

时间:2021-10-31 13:26:31

最近看到一个比较漂亮的UI主界面,该UI是用左边的页签进行导航,比较有特色,就想着尝试用WPF来实现一下。经过一番尝试,基本上将UI设计图的效果用WPF程序进行了实现。下面介绍一下主要的思路:

1 UI设计

 该UI的PSD设计图效果如下:

WPF如何实现一个漂亮的页签导航UI

  UI结构分析:先可以把UI分成上下两个区域,上面是一个区域放置一些appName,用户信息和配置按钮等,下面的再分成竖向的页签导航区域和内容区。但从WPF程序实现上来说,可以有多种区域划分方法,每个人的划分方法不同。

2 UI切图

  内容区域的图片不做切图,它会动态根据左边的导航菜单的配置动态进行加载内容。本文只实现主界面UI框架。在Photoshop中可以在图片所在图层进行重命名,例如A的图层有一个按钮图标,可以将其命名为A.png(注意之前需要勾选Photoshop的生成【图片资源】项目),那么就可以在PSD文件同级目录中生成一个同名的文件夹,里面就有A.png的图标了!

WPF如何实现一个漂亮的页签导航UI

3 WPF UI布局实现

  PSD设计的UI需要转换成WPF程序,必须要将其UI结构用WPF的布局进行重新梳理,我的布局划分(主要是Grid)代码如下所示:

 <Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="WpfTabNavigation.MainWindow"
Title="MainWindow" Height="610" Width="880"
AllowsTransparency="True" WindowStyle="None"
Background="{x:Null}" MouseLeftButtonDown="Window_MouseLeftButtonDown" >
<Grid Background="Black" d:IsHidden="True">
<Grid x:Name="gridForm" d:IsHidden="True">
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" x:Name="gridFormLeft"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- toolbar-->
<StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="1,1,1,0" Orientation="Horizontal" d:IsHidden="True" >
<StackPanel.Background>
<ImageBrush ImageSource="images/toolbarbg.png" Stretch="UniformToFill"/>
</StackPanel.Background> <Grid Width="878" d:IsHidden="True">
<Grid.RowDefinitions>
<RowDefinition Height="36" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="0.8*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="appName" FontWeight="Bold" FontSize="22" Margin="8,2,2,2" Text="WPF DashBoard" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center" d:IsHidden="True" />
<TextBlock x:Name="authorName" FontWeight="Bold" FontSize="10" Margin="8,0,2,8" Text="JackWang-Cumt@cnblogs.com" Foreground="#FF463E3E" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" d:IsHidden="True" /> <TextBlock x:Name="userInfo" FontWeight="Bold" FontSize="16" Margin="60,18,18,18" Text="Welcome to Admin" Foreground="#FF333333" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Center" d:IsHidden="True" /> <DatePicker x:Name="datePick" Margin="22.4,18,194.4,18" Foreground="#FF333333" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Center" Width="160" d:IsHidden="True"/>
<Image Source="images/email.png" Stretch="Uniform" Margin="0,15,112,19" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" Width="26" HorizontalAlignment="Right" d:IsHidden="True"/>
<Image Source="images/notify.png" Stretch="Uniform" Margin="254.4,9,102.4,10.2" Grid.Column="2" Grid.Row="0" Height="20" Width="20" d:IsHidden="True"/>
<TextBlock x:Name="notifyCount" FontSize="9" Margin="259.4,12,99.4,15.2" Grid.Column="2" Grid.Row="0" Text="18" Foreground="#FFFFFFFF" VerticalAlignment="Center" Width="18" d:IsHidden="True"/> <Image Source="images/settings.png" Stretch="Uniform" Margin="0,15,72,19" Grid.Column="2" Grid.Row="0" Height="26" Width="30" HorizontalAlignment="Right" Grid.RowSpan="2" d:IsHidden="True" />
<Image x:Name="Logout" MouseLeftButtonDown="Logout_MouseLeftButtonDown_1" Source="images/logout.png" Stretch="Uniform" Margin="0,15,36,19" Grid.Column="2" Grid.Row="0" Height="26" Width="30" HorizontalAlignment="Right" Grid.RowSpan="2" Cursor="Hand" d:IsHidden="True"/> </Grid>
</StackPanel>
<!--end toolbar-->
<StackPanel x:Name="LeftBar" Background="#FF333333" Margin="0,0.2,0,0" Grid.Column="0" Grid.Row="1" d:IsHidden="True" >
<TabControl x:Name="LeftTabControl" TabStripPlacement="Left" Background="#FF00D1E5" Height="548" d:IsHidden="True">
<TabItem Header="Home" Height="80" Margin="0,0,-3,0" Width="80" FontWeight="Bold" Style="{DynamicResource TabItemStyle}" TextOptions.TextFormattingMode="Display" MouseMove="TabItem_MouseMove_1" d:IsHidden="True">
<TabItem.Background>
<ImageBrush ImageSource="images/homeicon.png" />
</TabItem.Background> <StackPanel Margin="2,6,2,2" d:IsHidden="True" >
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" MouseLeftButtonDown="Label_MouseLeftButtonDown_1" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Web Design" Foreground="White" Margin="0,6,0,6" MouseLeftButtonDown="Label_MouseLeftButtonDown_2" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Icon Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="PSD Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Line Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Paper Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
</StackPanel> </TabItem>
<!-- Margin="0,0,-3,0" 中的-3为了消除右边的边框-->
<TabItem Header="Projects" Height="80" Margin="0,0,-3,0" Width="80" FontWeight="Bold" Style="{DynamicResource TabItemStyle}" TextOptions.TextFormattingMode="Display" d:IsHidden="True">
<TabItem.Background>
<ImageBrush ImageSource="images/projects.png" />
</TabItem.Background>
<!--内容区-->
<StackPanel Margin="2,6,2,2" d:IsHidden="True" >
<Label Content="CSS Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="JS Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="HTML Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
</StackPanel> <!--end 内容区--> </TabItem> <TabItem Header="Tasks" Height="80" Margin="0,0,-3,0" Width="80" FontWeight="Bold" Style="{DynamicResource TabItemStyle}" TextOptions.TextFormattingMode="Display" d:IsHidden="True">
<TabItem.Background>
<ImageBrush ImageSource="images/taskicon.png" />
</TabItem.Background>
<!--内容区-->
<StackPanel Margin="2,6,2,2" d:IsHidden="True" >
<Label Content="AI Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
</StackPanel> <!--end 内容区-->
</TabItem> <TabItem Header="Calendar" Height="80" Margin="0,0,-3,0" Width="80" FontWeight="Bold" Style="{DynamicResource TabItemStyle}" TextOptions.TextFormattingMode="Display" d:IsHidden="True">
<TabItem.Background>
<ImageBrush ImageSource="images/calendaricon.png" />
</TabItem.Background>
<!--内容区-->
<StackPanel Margin="2,6,2,2" d:IsHidden="True" >
<Label Content="DOC Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
</StackPanel> <!--end 内容区-->
</TabItem> <TabItem Header="Statistics" Height="80" Margin="0,0,-3,0" Width="80" FontWeight="Bold" Style="{DynamicResource TabItemStyle}" TextOptions.TextFormattingMode="Display" d:IsHidden="True">
<TabItem.Background>
<ImageBrush ImageSource="images/graphicon.png" />
</TabItem.Background>
<!--内容区-->
<StackPanel Margin="2,6,2,2" d:IsHidden="True" >
<Label Content="JD Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
<Label Content="Graphic Design" Foreground="White" Margin="0,6,0,6" d:IsHidden="True"/>
<Border d:IsHidden="True" >
<Image Source="images/line.png" d:IsHidden="True"/>
</Border>
</StackPanel> <!--end 内容区-->
</TabItem> </TabControl>
</StackPanel>
<!--end tab-->
<StackPanel Grid.Column="1" Grid.Row="1" Background="White" Margin="0,0,1,0" Orientation="Horizontal" d:IsHidden="True">
<!-- Expand button-->
<Border x:Name="spliter" Width="32" Height="64" Margin="-10" Cursor="Hand" MouseLeftButtonDown="spliter_MouseLeftButtonDown" d:IsHidden="True">
<Border.Background>
<ImageBrush ImageSource="images/panelexpand.png" Stretch="UniformToFill"/>
</Border.Background>
</Border> <!--end Expand button-->
<!--加载其他的page xaml-->
<Frame x:Name="pageContainer" Margin="33,18,33,18" ScrollViewer.CanContentScroll="True" NavigationUIVisibility="Hidden" d:IsHidden="True" />
<!--加载其他的xaml窗体,但是必须frm.show才能显示,有闪烁
<ContentControl Name="frmContainter" Margin="2" ></ContentControl>
-->
</StackPanel>
<!--end Content--> </Grid>
</Grid>
</Window>

  主界面中用 AllowsTransparency="True" WindowStyle="None" Background="{x:Null}" 对窗体的边框进行隐藏。坐标的页签是tabControl控件,但是必须要重新定义其Style样式:Style="{DynamicResource TabItemStyle},其中TabItemStyle的代码如下:

 <ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
<!-- 应该在此定义资源字典条目。-->
<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Padding" Value="4,4,4,4"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
<Setter Property="Background" Value="#F9F9F9"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid 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" MinHeight="84.5"/>
<RowDefinition x:Name="RowDefinition1"/>
</Grid.RowDefinitions>
<Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local" Margin="0">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Opacity="1"/>
</Border>
<Canvas x:Name="HeaderPanel" HorizontalAlignment="Stretch" Height="Auto" Width="Auto" IsItemsHost="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FF00D1E5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TabItemFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="3,3,3,1" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="TabItemHotBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#EAF6FD" Offset="0.15"/>
<GradientStop Color="#D9F0FC" Offset=".5"/>
<GradientStop Color="#BEE6FD" Offset=".5"/>
<GradientStop Color="#A7D9F5" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="TabItemSelectedBackground" Color="#F9F9F9"/>
<SolidColorBrush x:Key="TabItemHotBorderBrush" Color="#3C7FB1"/>
<SolidColorBrush x:Key="TabItemDisabledBackground" Color="#F4F4F4"/>
<SolidColorBrush x:Key="TabItemDisabledBorderBrush" Color="#FFC9C7BA"/>
<Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="FocusVisualStyle" Value="{StaticResource TabItemFocusVisual}"/>
<Setter Property="Foreground" Value="#FF00D1E5"/>
<Setter Property="Padding" Value="6,1,6,1"/>
<Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition Height="0.66*"/>
<RowDefinition Height="0.34*"/>
</Grid.RowDefinitions>
<Border x:Name="Bd" BorderThickness="0" CornerRadius="3" BorderBrush="Black" Margin="0" Grid.RowSpan="2" Visibility="Hidden">
<Border.Background>
<ImageBrush ImageSource="/WpfTabNavigation;component/images/hoverbutton.png" />
</Border.Background>
</Border>
<Border x:Name="fg" BorderThickness="0" CornerRadius="3" BorderBrush="#FF00D1D1" Margin="0" Grid.RowSpan="2" Visibility="Hidden" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
<Border.Background>
<ImageBrush ImageSource="/WpfTabNavigation;component/images/hoverbutton.png"/>
</Border.Background>
</Border>
<!--文本颜色设置-->
<TextBlock Name="PART_Text" Margin="0,0.333,0,3.833" TextWrapping="Wrap" VerticalAlignment="Stretch" d:LayoutOverrides="Height" Grid.Row="1" HorizontalAlignment="Center" Text="{TemplateBinding Header}" Foreground="Black" > <TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property= "Foreground" Value="#FF00D1E5"/>
<Style.Triggers>
<Trigger Property ="IsMouseOver" Value="True">
<Setter Property= "Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style> </TextBlock>
<!--图标-->
<Border x:Name="ico" BorderThickness="0" CornerRadius="3" BorderBrush="Black" Margin="4,4,4.25,0" Grid.RowSpan="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="32" Height="32" Background="{TemplateBinding Background}" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true"/>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Visibility" TargetName="Bd" Value="Visible"/>
<Setter Property="Panel.ZIndex" TargetName="ico" Value="1"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="false"/>
<Condition Property="IsMouseOver" Value="true"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="fg" Value="Visible"/>
<Setter Property="RenderTransform" TargetName="ico">
<Setter.Value>
<TransformGroup>
<ScaleTransform ScaleX="1.05" ScaleY="1.05"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Setter.Value>
</Setter>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

4 WPF逻辑实现

 UI界面有了,还必须附加一些业务逻辑:

 1)窗体拖动;

         private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}

2)单击页签菜单项目,进行导航到相应的页面;

         private void Label_MouseLeftButtonDown_2(object sender, MouseButtonEventArgs e)
{
this.pageContainer.Source = new Uri("pages/Page_Chart2.xaml", UriKind.RelativeOrAbsolute);
}

  在主界面中有一个名为pageContainer的Frame控件,它能加载Page类型的界面(注意不是window).详细页面的正太分布图形用的Oxyplot控件。

 3)坐标的页签菜单栏可以隐藏和显示

         private bool __isLeftHide = false;
private void spliter_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//显示和隐藏
__isLeftHide =! __isLeftHide;
if (__isLeftHide)
{
this.gridForm.ColumnDefinitions[].Width = new GridLength(1d);
}
else
{
this.gridForm.ColumnDefinitions[].Width = new GridLength(200d);
} }

  由于Grid没有visiable属性,我这里获取页签所在的Grid列,然后设置其width属性为1,将其隐藏。

5 最终效果

  最终的效果截图如下(感谢园友斧正:下图的正太分布是正态分布哈!):

WPF如何实现一个漂亮的页签导航UI

6 未实现的功能

  左边菜单的颜色,想着不选中显示RGB(0,209,229),选中显示RGB(51,51,51)或者黑色。但尝试了一些方法还未实现。若有园友知道思路的话,欢迎指教!

7 代码开源

  此代码进行开源,代码托管到GitHub上,https://github.com/JackWangCUMT/WPFTabNavigation

-----------------------------------------------------------------------------------------------------------------

8 完善

  上面提到字体无法变更的问题,经过查阅资料已经解决,这里主要用到触发器设置中的TargetName属性,将设置的值应用到名为TargetName设置的控件对应属性上:

WPF如何实现一个漂亮的页签导航UI

     <Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}">
......
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid SnapsToDevicePixels="true">
......
<!--页签文本 PART_Text-->
<TextBlock Name="PART_Text" Margin="0,0.333,0,3.833" TextWrapping="Wrap" VerticalAlignment="Stretch" d:LayoutOverrides="Height" Grid.Row="1" HorizontalAlignment="Center" Text="{TemplateBinding Header}" Foreground="#FF00D1E5" > </TextBlock>
<!--图标-->
......
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true"/>
<!--页签选中后进行触发-->
<Trigger Property="IsSelected" Value="true">
<Setter Property="Visibility" TargetName="Bd" Value="Visible"/>
<Setter Property="Panel.ZIndex" TargetName="ico" Value="1"/>
<!--在控件模板下,一个控件的Triggers可利用TargetName属性对其他控件的样式-->
<Setter Property="Foreground" TargetName="PART_Text" Value="Black" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="false"/>
<Condition Property="IsMouseOver" Value="true"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="fg" Value="Visible"/>
<Setter Property="RenderTransform" TargetName="ico">
<Setter.Value>
<TransformGroup>
<ScaleTransform ScaleX="1.05" ScaleY="1.05"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Setter.Value>
</Setter>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

另外将日期控件进行了样式完善,这里对TextBox控件利用自定义样式将其设置为具有可以下拉选择日期的功能。

WPF如何实现一个漂亮的页签导航UI