原文: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 1226】Substrings

    [链接]h在这里写链接 [题意] 给你n个字符串. 让你找一个字符串s. 设s'为这个字符串的逆序. 要求s或者s'在每个字符串里都能够找得到. 并且要求s的长度最长. 求出这个最长的串的长度. [题 ...

  2. 【SPOJ 694】Distinct Substrings

    [链接]h在这里写链接 [题意]     给你一个长度最多为1000的字符串     让你求出一个数x,这个x=这个字符串的不同子串个数; [题解]     后缀数组题.     把原串复制一份,加在 ...

  3. hdu 5375 Gray code dp

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; cons ...

  4. java.util.logging使用笔记2

      java.util.logging是java自带的日志处理系统,其功能不如log4j/logback强大,但可以完成基本的日志需求. 另外,如果在一个项目中使用log4j, 而这个项目引用的第3方 ...

  5. 8、linux下输入子系统

    input_sync(button_dev);    /*通知接收者,一个报告发送完毕*/ 参考:http://www.51hei.com/bbs/dpj-27652-1.html  很详细说明 in ...

  6. [PReact] Use Link State to Automatically Handle State Changes

    Storing and updating values inside a component’s local state (known as controlled components) is suc ...

  7. POJ 1751 Highways (ZOJ 2048 ) MST

    http://poj.org/problem?id=1751 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2048 题目大 ...

  8. cmder显示UTF-8字体

    https://blog.csdn.net/x_iya/article/details/50627829 WIN+ALT+P打开配置 搜索chcp chcp 65001

  9. andorid 自己定义SwitchButton

    因项目缘故需又一次定制SwitchButton,效果例如以下:   步骤例如以下: 1.圆角矩形的绘制 2.字体绘制 3.小圆绘制 4.左右滑动动画效果绘制 代码例如以下: package com.s ...

  10. ios开发网络学习五:MiMEType ,多线程下载文件思路,文件的压缩和解压缩

    一:MiMEType:一般可以再百度上搜索到相应文件的MiMEType,或是利用c语言的api去获取文件的MiMEType : //对该文件发送一个异步请求,拿到文件的MIMEType - (void ...