原文:C# WPF 左侧菜单右侧内容布局效果实现

我们要做的效果是这样的,左侧是可折叠的菜单栏,右侧是内容区域,点击左侧的菜单项右侧内容区域则相应地切换。

wpf实现的话,我的办法是用一个tabcontrol,修改tabcontrol的样式模板,首先将控件的TabStripPlacement设置为left使tabcontrol的item header部分靠左内容靠右,然后用一个Expander将TabPanel包住实现可折叠菜单效果,最后就是把用到的控件样式修改一下即可。

先看下效果图:

WPF做出来的效果图:

未完善的问题:

不能添加多个可折叠菜单,我暂时没想到比较好的办法。

新建一个项目,名字随你,新建一个自定义用户控件前台修改为:

<TabControl x:Class="cloundmusic_left.controls.itabcontrol"
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:cloundmusic_left.controls"
mc:Ignorable="d"
d:DesignHeight="" d:DesignWidth="">
<TabControl.Resources>
<!--折叠菜单的箭头按钮-->
<ControlTemplate x:Key="ExpanderToggleButton"
TargetType="{x:Type ToggleButton}">
<Border Background="{TemplateBinding Background}" Width="{TemplateBinding Width}" x:Name="Border"
> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="CollapsedArrow">
<DiscreteObjectKeyFrame KeyTime=""
Value="{x:Static Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="ExpandededArrow">
<DiscreteObjectKeyFrame KeyTime=""
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="0,0,13,0" HorizontalAlignment="Right" VerticalAlignment="Center">
<Path x:Name="CollapsedArrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z">
<Path.Fill>
<SolidColorBrush Color="#7d7d7d" />
</Path.Fill>
</Path>
<Path x:Name="ExpandededArrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="Collapsed"
Data="M 0 4 L 4 0 L 8 4 Z">
<Path.Fill>
<SolidColorBrush Color="#7d7d7d" />
</Path.Fill>
</Path>
</Grid>
</Border>
</ControlTemplate> <Style TargetType="{x:Type Expander}">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="#7d7d7d"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border BorderBrush="#e1e1e2" BorderThickness="0,0,1,0">
<Grid Background="#f5f5f7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition x:Name="ContentRow"
Height="" />
</Grid.RowDefinitions> <Border MinHeight="" x:Name="Border"
Grid.Row=""
> <Grid VerticalAlignment="Center"> <ContentPresenter
Margin="" ContentSource="Header"
RecognizesAccessKey="True" /> <ToggleButton Background="Transparent" Width="{Binding ElementName=Border,Path=ActualWidth}" Panel.ZIndex="" OverridesDefaultStyle="True"
Template="{StaticResource ExpanderToggleButton}"
IsChecked="{Binding IsExpanded, Mode=TwoWay,
RelativeSource={RelativeSource TemplatedParent}}"> </ToggleButton>
</Grid>
</Border>
<Border x:Name="Content"
Grid.Row=""
> <ContentPresenter/>
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded"
Value="True">
<Setter TargetName="ContentRow"
Property="Height"
Value="{Binding DesiredHeight, ElementName=Content}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <Style TargetType="{x:Type TabItem}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid SnapsToDevicePixels="true">
<Border Cursor="Hand" MinWidth="" MinHeight="" x:Name="Bd" CornerRadius="" Background="Transparent" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="3,0,0,0" Padding="" Margin="">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<StackPanel Orientation="Horizontal"> <ContentPresenter x:Name="Content" Margin="17,0,0,0" ContentSource="Header" HorizontalAlignment="Left" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/> </StackPanel> </Grid>
</Border>
</Grid> <ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="false"> <Setter Property="Foreground" Value="#5c5c5c"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true"> <Setter Property="Foreground" Value="#000000"/>
</Trigger> <Trigger Property="IsSelected" Value="true">
<Setter Property="Panel.ZIndex" Value=""/>
<Setter Property="Background" TargetName="Bd" Value="#e6e7ea"/> <Setter Property="Foreground" Value="#000000"/>
<Setter Property="BorderThickness" TargetName="Bd" Value="3,0,0,0"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="#c62f2f"/> </Trigger> </ControlTemplate.Triggers>
</ControlTemplate> </Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabControl.Style>
<Style TargetType="{x:Type TabControl}">
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="TabStripPlacement"
Value="Left" />
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:itabcontrol}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> <!--可折叠菜单-->
<Expander Header="{TemplateBinding iTitle}" Grid.Column="">
<!--菜单项-->
<TabPanel x:Name="HeaderPanel" IsItemsHost="True"
KeyboardNavigation.TabIndex=""
Background="Transparent" />
</Expander>
<!--右侧内容区域-->
<Border x:Name="Border"
Grid.Column="" KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex=""> <ContentPresenter x:Name="PART_SelectedContentHost"
Margin=""
ContentSource="SelectedContent" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </TabControl.Style>
</TabControl>

修改后你的vs也许会抱一个错:

这个报错就像vs错误列表里的警告一样,没啥卵用,不用理它,程序是可以运行的

ok继续,后台代码加一个依赖属性:

 public string iTitle
{
get { return (string)GetValue(iTitleProperty); }
set { SetValue(iTitleProperty, value); }
} public static readonly DependencyProperty iTitleProperty =
DependencyProperty.Register("iTitle", typeof(string), typeof(itabcontrol));

然后只要在界面中使用这个控件即可。

呃我发现这个项目并没有什么难点,实现方法开头也说了,所以这里不一步步讲了。

值得一提的是,加入的Expander也就是可折叠菜单的header代表菜单名,这里我是把修改的这个TabControl写在一个自定义控件里的,在界面调用的时候默认是无法给它设置内容的,所以我们要在这个自定义控件中加入一个依赖属性,然后在样式中绑定这个属性。这里就涉及到一个比较有意思的东西,在样式中绑定一个属性也许你没接触过,但是你一定知道Binding的用法,而在样式中是没办法这么用的,那该怎么去做呢?相信你看完代码就知道了。

项目下载:

点我下载

C# WPF 左侧菜单右侧内容布局效果实现的更多相关文章

  1. 左侧菜单栏右侧内容(改进,有js效果)

    (如有错敬请指点,以下是我工作中遇到并且解决的问题)上一篇文章是简洁版 这是上一篇文章的改进. 上一篇文章的左侧菜单是没有子目录的. 这是效果图: 左侧菜单代码: <div class=&quo ...

  2. HTMLCSS实现左侧固定宽度右侧内容可滚动

    在做移动端页面的时候,经常会碰到一个div中分左右两个div,左侧div固定宽度或百分比,右侧div中内容左右溢出,需要左右滑动才可以浏览到全部内容,为此写了一个demo. 处理这个问题的核心关键点是 ...

  3. HTML和CSS实现左侧固定宽度右侧内容可滚动

    在做移动端页面的时候,经常会碰到一个div中分左右两个div,左侧div固定宽度或百分比,右侧div中内容左右溢出,需要左右滑动才可以浏览到全部内容,为此写了一个demo. 处理这个问题的核心关键点是 ...

  4. C# 窗体 类似framest 左侧点击右侧显示 左侧菜单右侧显示

    首先托一个splitContainer调节大小位置 然后进行再新创建一个窗体名为add 在左侧拖入button按钮 进入代码阶段 更改属性 public Main() { InitializeComp ...

  5. css布局之左侧固定右侧自适应布局

    参考代码如下: <form id="form1" style="height:100%; overflow:hidden;"> <div st ...

  6. bootstrap实现左侧图片右侧文字布局

    效果图 代码 通过class="media-left"来控制相对位置 <!DOCTYPE html> <html> <head lang=" ...

  7. ifram 实现左侧菜单,右侧显示内容

    一般都是左侧的导航栏中的a标签中写一个target(a标签有target属性), 右侧的div标签中写一个iframe,在iframe中有name的属性,在左侧a标签中的target写上iframe中 ...

  8. ionic js 侧栏菜单 把主要内容区域从一边拖动到另一边,来让左侧或右侧的侧栏菜单进行切换

    ionic 侧栏菜单 一个容器元素包含侧边菜单和主要内容.通过把主要内容区域从一边拖动到另一边,来让左侧或右侧的侧栏菜单进行切换. 效果图如下所示: 用法 要使用侧栏菜单,添加一个父元素<ion ...

  9. ajax实现简单的点击左侧菜单,右侧加载不同网页

    实现:ajax实现点击左侧菜单,右侧加载不同网页(在整个页面无刷新的情况下实现右侧局部刷新,用到ajax注意需要在服务器环境下运行,从HBuilder自带的服务器中打开浏览效果即可) 原理:ajax的 ...

随机推荐

  1. POJ 1952 BUY LOW, BUY LOWER DP记录数据

    最长递减子序列.加记录有多少个最长递减子序列.然后须要去重. 最麻烦的就是去重了. 主要的思路就是:全面出现反复的值,然后还是同样长度的子序列.这里的DP记录的子序列是以当前值为结尾的时候,而且一定选 ...

  2. [array] leetCode-15. 3Sum-Medium

    leetCode-15. 3Sum-Medium descrition Given an array S of n integers, are there elements a, b, c in S ...

  3. Linux 下配置 Python IDE——Emacs

    工欲善其事,必先利其器.Python作为高级语言,因为其简介.灵活已经被越来越多的程序员所青睐.在尝试了众多IDE之后,终于找到了自己的挚爱.废话少说,下面开始说一下如何在linux下安装配置Emac ...

  4. 嵌入式/X86下linux系统死机及内存优化

    一.  CPU 过高或死锁导致系统卡死 1. CPU占用过高 (1)开线程太多导致CPU占用过高,系统卡死 解决:优化应用层业务逻辑,有些业务不必开线程就不开 (2)频繁清缓存导致读spi-flash ...

  5. 《SPA设计与架构》之JavaScript模块化

    原文 简书原文:https://www.jianshu.com/p/d5fc38506bc4 大纲 1.什么是模块? 2.基本的模块模式 3.模块模式概念 4.模块结构 5.揭示模式 6.模块编程的意 ...

  6. [Ramda] allPass, propEq

    const needs = ['wifi', 'shower', 'laundry']; const homes = [{ name: 'Home 1', wifi: 'y', shower: 'y' ...

  7. Qt5 编译 & 打包依赖dll发布

    十年前学C++的时候,无聊到把windows 文件夹下几乎所有的*.dll 都看过一遍.偶尔在程序运行时看到缺少 *.dll 的提示,都会直接找出来解决. 随着“开发平台”和“编译器”版本的逐年升级, ...

  8. 在Excel中粘贴时怎样跳过隐藏行

    http://www.excel123.cn/Article/exceljichu/201203/932.html 有时在筛选后需要将其他区域中的连续行数据复制粘贴到筛选区域,以替换筛选后的数据.由于 ...

  9. CentOS下安装和配置MySQL-JDK-Tomcat-Nginx(个人官网环境搭建手册)

    今天,重新弄我的个人云主机的环境,准备运营自己用Java写的个人官网等网站. 服务器环境:阿里云CentOS 6.4位 包括以下脚本在内的绝大部分命令和脚本,都是我亲自执行过,靠谱的. 完整的&quo ...

  10. js进阶 11-6 jquery如何获取和设置元素的宽高(jquery多方法)

    js进阶 11-6  jquery如何获取和设置元素的宽高(jquery多方法) 一.总结 一句话总结:jquery里面多是方法啊,比如jquery对象的宽高.所以取值是方法,赋值就是方法里面带参数. ...