文档章节

WPF模拟Office2010文件菜单的TabControl模板

墙头草
 墙头草
发布于 2012/12/04 14:50
字数 1201
阅读 11671
收藏 8
WPF


这是Office2010中的文件菜单点开后的效果。本文我将以强大的WPF(www.itstrike.cn)来实现类似的效果。希望你能有所收获。而不是只拷贝/粘贴代码而已。

开始之前。先把TabControl找个地方放着。

<Window x:Class="TestClient.MainWindow"

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

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

        Title="MainWindow" Height="350" Width="525">

    <TabControl Name="tabSteps">

        <TabItem Header="Info" IsSelected="True">

            <TextBlock>Info content</TextBlock>

        </TabItem>

        <TabItem Header="Recent">

            <TextBlock>Recent content tab</TextBlock>

        </TabItem>

        <TabItem Header="New">

            <TextBlock>New content tab</TextBlock>

        </TabItem>

        <TabItem Header="Print">

            <TextBlock>Print content tab</TextBlock>

        </TabItem>

        <TabItem Header="Save &amp; Send">

            <TextBlock>Save &amp; send content tab</TextBlock>

        </TabItem>

        <TabItem Header="Help">

            <TextBlock>Help tab</TextBlock>

        </TabItem>

    </TabControl>

</Window>


然后会大概是这个效果

为了改变TabControl的显示效果。我们使用模板机制,我们把模板写进一个资源字典里。这样就可以重用了。添加一个资源字典的步骤如下

右键点击工程-添加-资源字典

然后在资源字典里添加一些代码。

  <ControlTemplate x:Key="OfficeTabControl" TargetType="{x:Type TabControl}">

        <Grid>

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="160" />

                <ColumnDefinition/>

            </Grid.ColumnDefinitions>

            <Border Background="#FFE9ECEF"

                    Grid.Column="0"

                    BorderBrush="LightGray"

                    BorderThickness="1"

                    SnapsToDevicePixels="True" />

            <StackPanel IsItemsHost="True"

                        Grid.Column="0"

                        Margin="0,0,-1,0"

                        SnapsToDevicePixels="True" />

            <ContentPresenter

                Content="{TemplateBinding SelectedContent}"

                Grid.Column="1"

                Margin="15,0,0,0" />

        </Grid>

    </ControlTemplate>


这样就添加了一个有一个grid元素的名为OfficeTabControl的控件模板 . Grid 被分成两列,一列是标签页,一列是页内容。左边的列包含一个灰色背景和亮灰色的边缘线,然后一个StackPanel,IsItemsHost属性被设置为true,

这样标签项被会放在这个栈面板里。第二列是ContentPresenter 这会放置标签页内容。然后让我们前面的TabControl使用新模板。设置Template 属性。

 <Window.Resources>

        <ResourceDictionary>

            <ResourceDictionary.MergedDictionaries>

                <ResourceDictionary Source="OfficeTab.xaml" />

            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>

    </Window.Resources>

    <TabControl Name="tabSteps" Template="{StaticResource OfficeTabControl}">

在这之前,先把资源字典加到窗体的Reesouce里。然后再设置。然后运行软件。效果会有一些不一样。

然后要修改左侧单个标签的显示效果。通过改变模板来实现。给模板添加如下的代码

<ControlTemplate x:Key="OfficeTabControl" TargetType="{x:Type TabControl}">

    <ControlTemplate.Resources>

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

            <Setter Property="Template">

                <Setter.Value>

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

                        <Grid SnapsToDevicePixels="True">

                            <ContentPresenter

                                Name="buttonText"

                                Margin="15,0,5,0"

                                TextBlock.FontFamily="Calibri"

                                TextBlock.FontSize="12pt"

                                TextBlock.Foreground="Black"

                                Content="{TemplateBinding Header}"

                                VerticalAlignment="Center"/>

                        </Grid>

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

    </ControlTemplate.Resources>

然后再运行

VisualState很有意思。我们可以放在Grid里。然后设置正常状态和鼠标悬停的状态。

为了添加鼠标悬停效果,我们添加两个Borders元素。一个右边缘是灰线,另一个用在背景上。亮蓝色放在上下边缘

<Border Name="hoverShape"

        Height="40"

        Margin="0,0,1,0"

        SnapsToDevicePixels="True"

        BorderThickness="0,0,1,0"

        BorderBrush="LightGray">

    <Border BorderBrush="#FFA1B7EA"

            BorderThickness="0,1"

            Background="#FFE5EEF9"

            Height="40"

            SnapsToDevicePixels="True" />

</Border>

之后,我们为VisualState创建故事板,一个是正常状态。会使得hoverShape的透明度为0.另一个是鼠标悬停的状态。透明度会变成1

<Grid SnapsToDevicePixels="True">

    <VisualStateManager.VisualStateGroups>

        <VisualStateGroup Name="CommonStates">

            <VisualState Name="MouseOver">

                <Storyboard>

                    <DoubleAnimation

                        Storyboard.TargetName="hoverShape"

                        Storyboard.TargetProperty="Opacity"

                        To="1"

                        Duration="0:0:.1"/>

                </Storyboard>

            </VisualState>

            <VisualState Name="Normal">

                <Storyboard>

                    <DoubleAnimation

                        Storyboard.TargetName="hoverShape"

                        Storyboard.TargetProperty="Opacity"

                        To="0"

                        Duration="0:0:.1"/>

                </Storyboard>

            </VisualState>

        </VisualStateGroup>

之后效果如下

然后添加选中项的样式,在hoverShape 下面再添加一个Border,名字是buttonShape。通过这个我们给被选中项的上下边缘添加2个像素的黑蓝色边缘,

在 Expression Blend中打开, 使用钢笔工具绘制个你想要的路径形状即可。然后把生成的xaml代码拷些过来。

也可以直接用我的代码。。不顾我说过要怎么做了。

最终看起来应该是这样的。

<Border

    Name="buttonShape"

    Opacity="0"

    BorderBrush="#FF0343A6"

    BorderThickness="0,2"

    Height="40"

    SnapsToDevicePixels="True">

    <Path

        Data="M214,108 L346,108 346.125,118.125 337.75,126.125

                   346.375,134 346.375,143.875 214.25,144.25 z"

        SnapsToDevicePixels="True"

        Stretch="Fill"

        Height="40">

        <Path.Fill>

            <RadialGradientBrush GradientOrigin="0.2,0.5" RadiusX="0.8" RadiusY="0.8">

                <GradientStop Color="#FF5FA3F6" Offset="0" />

                <GradientStop Color="#FF0C55B9" Offset="1" />

            </RadialGradientBrush>

        </Path.Fill>

    </Path>

</Border>

当你运行的时候你会发现没什么变化。我们还要定义被选中标签的VisualState

当添加如下代码的时候 添加一个VisualState组。也就是 SelectionStates ,然后给选中/为选中的状态添加行为/故事板。.这里通过修改透明度来实现一些效果

<VisualStateGroup Name="SelectionStates">

    <VisualState Name="Selected">

        <Storyboard>

            <DoubleAnimation

                Storyboard.TargetName="buttonShape" Storyboard.TargetProperty="Opacity"

                To="1" Duration="0:0:.3"/>

            <DoubleAnimation

                Storyboard.TargetName="hoverShape" Storyboard.TargetProperty="Opacity"

                To="0" Duration="0:0:.1"/>

            <ColorAnimation

                Storyboard.TargetName="buttonText"

                Storyboard.TargetProperty=

                            "(TextBlock.Foreground).(SolidColorBrush.Color)"

                To="White" Duration="0:0:.1" />

        </Storyboard>

    </VisualState>

    <VisualState Name="Unselected">

        <Storyboard>

            <DoubleAnimation

                Storyboard.TargetName="buttonShape"

                Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:.1"/>

            <DoubleAnimation

                Storyboard.TargetName="hoverShape"

                Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:.1"/>

        </Storyboard>

    </VisualState>

</VisualStateGroup>

现在再运行会发现效果更好了

还有个小问题,就是那个陷进入的小三角形的背景颜色依然还在。通过在下面添加一个白色的形状。,并且对故事板的选中和为选中状态改变一下透明度就可以了。

<VisualStateGroup Name="SelectionStates">

    <VisualState Name="Selected">

        <Storyboard>

            <DoubleAnimation

                Storyboard.TargetName="buttonBackgroundShape"

                Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>

        </Storyboard>

    </VisualState>

    <VisualState Name="Unselected">

        <Storyboard>

            <DoubleAnimation

                Storyboard.TargetName="buttonBackgroundShape"

                Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>

        </Storyboard>

    </VisualState>

</VisualStateGroup>

最终效果如下:


© 著作权归作者所有

墙头草
粉丝 16
博文 145
码字总数 117172
作品 0
卢湾
私信 提问
加载中

评论(8)

rosem_九心
rosem_九心
InvalidOperationException: 无法在“System.Windows.Controls.Grid”的名称领域内找到“hoverShape”名称。
LSLilei
LSLilei
这个。。有些地方没有讲清楚代码插在那里。新手看不懂唉
宋云涛
宋云涛
貌似这样可以:
<Border
Name="buttonBackgroundShape"
Opacity="0"
BorderBrush="#FF0343A6"
BorderThickness="0,2"
Height="40"
SnapsToDevicePixels="True">
<Path Data="M624,254 L584,262.5 623.75,272" HorizontalAlignment="Right" Stretch="Fill" Width="13.5" Margin="0,11.25,0,6">
<Path.Fill>
<RadialGradientBrush GradientOrigin="0.2,0.5" RadiusX="0.8" RadiusY="0.8">
<GradientStop Color="#FFFFFFFF" Offset="0" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</RadialGradientBrush>
</Path.Fill> </Path> </Border>
宋云涛
宋云涛
貌似这样可以:
<Border
Name="buttonBackgroundShape"
Opacity="0"
BorderBrush="#FF0343A6"
BorderThickness="0,2"
Height="40"
SnapsToDevicePixels="True">
<Path Data="M624,254 L584,262.5 623.75,272" HorizontalAlignment="Right" Stretch="Fill" Width="13.5" Margin="0,11.25,0,6">
<Path.Fill>
<RadialGradientBrush GradientOrigin="0.2,0.5" RadiusX="0.8" RadiusY="0.8">
<GradientStop Color="#FFFFFFFF" Offset="0" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</RadialGradientBrush>
</Path.Fill> </Path> </Border>
宋云涛
宋云涛
buttonBackgroundShape 这个东东在哪里定义的。可否告知
kps
kps
可否发一份demo啊
大王叫我来巡山__
大王叫我来巡山__
对于一个新手来说,楼主讲的不是很清楚啊
江上烟波
江上烟波
其实我想问源码有没有。
wpf的TabControl的跳转问题

求高手指教!!!!? TabControl的SelectedIndex、Focus的冲突吗? 我在不同的构造方法中通过设置tabControl1的selectedIndex来跳转到不同的TabItem页, 因为每次在不同页中跳转时焦点会出现...

xiongmiao
2012/10/25
10.3K
9
WPF 控件库——可拖动选项卡的TabControl

一、先看看效果 二、原理 1、选项卡大小和位置   这次给大家介绍的控件是比较常用的TabControl,网上常见的TabControl样式有很多,其中一部分也支持拖动选项卡,但是带动画效果的很少见。这...

纳边
2018/09/11
0
0
WPF中DataTemplate基本原理与缺陷分析

这个文章来源于这样一个问题。下面的两种做 法,在效果上有什么不同?(注:Header是一个自定义DP。) 和 一种是直接在TabItem里放一个TextBox,另一种是通过DataTemplate间接地放进去。这两...

andrewniu
2018/05/30
0
0
monodevelop如何实现tabcontrol

monodevelop如何实现tabcontrol

dlw
2012/02/21
394
0
请问,winform的tabcontrol控件怎么设置透明呢?

请问,winform的tabcontrol控件怎么设置透明呢?谢谢!

mayrose
2016/01/14
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

jQuery使用GET方式来进行异步请求

jQuery.get( url, [data], [callback] ):使用GET方式来进行异步请求 参数: url(String) : 发送请求的URL地址. data(Map) : (可选) 要发送给服务器的数据,以 Key/value 的键值对形式表示,...

前端老手
19分钟前
5
0
网络安全市场需求

最近,网络安全技能差距的热门话题流传开来。技能差距经常被紧急讨论,可以看出它在实践中的作用是很大的。但信息安全是一门广泛的学科,所以在谈论“技能差距”时需要更具体。有专家表示,真...

linuxCool
36分钟前
4
0
定期批量改密,实现高效运维,保障口令安全

随着企业IT资产规模的不断增大,各类主机、应用系统的管理也变得愈加困难。 对于系统管理员来说,保证操作系统的密码安全是其重要工作,在需要维护众多的主机时,其面临的困境将是: 1、难以...

堡垒啊
今天
5
0
怎样在磁盘上查找MySQL表的大小?这里有答案

导读 我想知道 MySQL 表在磁盘上占用多少空间,但看起来很琐碎。不应该在 INFORMATION_SCHEMA.TABLES 中提供这些信息吗?没那么简单! 我想知道 MySQL 表在磁盘上占用多少空间,但看起来很琐碎...

问题终结者
今天
6
0
Spring Boot缓存实战 Redis 设置有效时间和自动刷新缓存-2

问题 上一篇Spring Boot Cache + redis 设置有效时间和自动刷新缓存,时间支持在配置文件中配置,说了一种时间方式,直接扩展注解的Value值,如: @Override@Cacheable(value = "people#${s...

xiaolyuh
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部