我们要做的效果是这样的,左侧是可折叠的菜单栏,右侧是内容区域,点击左侧的菜单项右侧内容区域则相应地切换。
wpf实现的话,我的办法是用一个tabcontrol,修改tabcontrol的样式模板,首先将控件的TabStripPlacement设置为left使tabcontrol的item header部分靠左内容靠右,然后用一个Expander将TabPanel包住实现可折叠菜单效果,最后就是把用到的控件样式修改一下即可。
先看下效果图:
WPF做出来的效果图:
未完善的问题:
不能添加多个可折叠菜单,我暂时没想到比较好的办法。
新建一个项目,名字随你,新建一个自定义用户控件前台修改为:
"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="300" d:DesignWidth="300"> "ExpanderToggleButton" TargetType="{x:Type ToggleButton}"> "{TemplateBinding Background}" Width="{TemplateBinding Width}" x:Name="Border" > "CheckStates"> "Checked"> "(UIElement.Visibility)" Storyboard.TargetName="CollapsedArrow"> "0" Value="{x:Static Visibility.Hidden}" /> "(UIElement.Visibility)" Storyboard.TargetName="ExpandededArrow"> "0" Value="{x:Static Visibility.Visible}" /> "Unchecked" /> "Indeterminate" /> "0,0,13,0" HorizontalAlignment="Right" VerticalAlignment="Center"> "CollapsedArrow" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z"> "#7d7d7d" /> "ExpandededArrow" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed" Data="M 0 4 L 4 0 L 8 4 Z"> "#7d7d7d" /> "</span><span style="color: #800000;">{x:Type Expander}</span><span style="color: #800000;">"</span>> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Cursor</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">Hand</span><span style="color: #800000;">"</span>/> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Foreground</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">#7d7d7d</span><span style="color: #800000;">"</span>/> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Template</span><span style="color: #800000;">"</span>> <Setter.Value> <ControlTemplate TargetType=<span style="color: #800000;">"</span><span style="color: #800000;">{x:Type Expander}</span><span style="color: #800000;">"</span>> <Border BorderBrush=<span style="color: #800000;">"</span><span style="color: #800000;">#e1e1e2</span><span style="color: #800000;">"</span> BorderThickness=<span style="color: #800000;">"</span><span style="color: #800000;">0,0,1,0</span><span style="color: #800000;">"</span>> <Grid Background=<span style="color: #800000;">"</span><span style="color: #800000;">#f5f5f7</span><span style="color: #800000;">"</span>> <Grid.RowDefinitions> <RowDefinition Height=<span style="color: #800000;">"</span><span style="color: #800000;">Auto</span><span style="color: #800000;">"</span> /> <RowDefinition x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">ContentRow</span><span style="color: #800000;">"</span><span style="color: #000000;"> Height</span>=<span style="color: #800000;">"</span><span style="color: #800000;">0</span><span style="color: #800000;">"</span> /> </Grid.RowDefinitions> <Border MinHeight=<span style="color: #800000;">"</span><span style="color: #800000;">32</span><span style="color: #800000;">"</span> x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">Border</span><span style="color: #800000;">"</span><span style="color: #000000;"> Grid.Row</span>=<span style="color: #800000;">"</span><span style="color: #800000;">0</span><span style="color: #800000;">"</span> > <Grid VerticalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Center</span><span style="color: #800000;">"</span>> <<span style="color: #000000;">ContentPresenter Margin</span>=<span style="color: #800000;">"</span><span style="color: #800000;">4</span><span style="color: #800000;">"</span><span style="color: #000000;"> ContentSource</span>=<span style="color: #800000;">"</span><span style="color: #800000;">Header</span><span style="color: #800000;">"</span><span style="color: #000000;"> RecognizesAccessKey</span>=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span> /> <ToggleButton Background=<span style="color: #800000;">"</span><span style="color: #800000;">Transparent</span><span style="color: #800000;">"</span> Width=<span style="color: #800000;">"</span><span style="color: #800000;">{Binding ElementName=Border,Path=ActualWidth}</span><span style="color: #800000;">"</span> Panel.ZIndex=<span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span> OverridesDefaultStyle=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span><span style="color: #000000;"> Template</span>=<span style="color: #800000;">"</span><span style="color: #800000;">{StaticResource ExpanderToggleButton}</span><span style="color: #800000;">"</span><span style="color: #000000;"> IsChecked</span>=<span style="color: #800000;">"</span><span style="color: #800000;">{Binding IsExpanded, Mode=TwoWay, </span> RelativeSource={RelativeSource TemplatedParent}}<span style="color: #800000;">"</span><span style="color: #800000;">></span> </ToggleButton> </Grid> </Border> <Border x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">Content</span><span style="color: #800000;">"</span><span style="color: #000000;"> Grid.Row</span>=<span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span> > <ContentPresenter/> </Border> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property=<span style="color: #800000;">"</span><span style="color: #800000;">IsExpanded</span><span style="color: #800000;">"</span><span style="color: #000000;"> Value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span>> <Setter TargetName=<span style="color: #800000;">"</span><span style="color: #800000;">ContentRow</span><span style="color: #800000;">"</span><span style="color: #000000;"> Property</span>=<span style="color: #800000;">"</span><span style="color: #800000;">Height</span><span style="color: #800000;">"</span><span style="color: #000000;"> Value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">{Binding DesiredHeight, ElementName=Content}</span><span style="color: #800000;">"</span> /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> "</span><span style="color: #800000;">{x:Type TabItem}</span><span style="color: #800000;">"</span>> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">OverridesDefaultStyle</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span>/> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Template</span><span style="color: #800000;">"</span>> <Setter.Value> <ControlTemplate TargetType=<span style="color: #800000;">"</span><span style="color: #800000;">{x:Type TabItem}</span><span style="color: #800000;">"</span>> <Grid SnapsToDevicePixels=<span style="color: #800000;">"</span><span style="color: #800000;">true</span><span style="color: #800000;">"</span>> <Border Cursor=<span style="color: #800000;">"</span><span style="color: #800000;">Hand</span><span style="color: #800000;">"</span> MinWidth=<span style="color: #800000;">"</span><span style="color: #800000;">199</span><span style="color: #800000;">"</span> MinHeight=<span style="color: #800000;">"</span><span style="color: #800000;">32</span><span style="color: #800000;">"</span> x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">Bd</span><span style="color: #800000;">"</span> CornerRadius=<span style="color: #800000;">"</span><span style="color: #800000;">0</span><span style="color: #800000;">"</span> Background=<span style="color: #800000;">"</span><span style="color: #800000;">Transparent</span><span style="color: #800000;">"</span> BorderBrush=<span style="color: #800000;">"</span><span style="color: #800000;">{TemplateBinding BorderBrush}</span><span style="color: #800000;">"</span> BorderThickness=<span style="color: #800000;">"</span><span style="color: #800000;">3,0,0,0</span><span style="color: #800000;">"</span> Padding=<span style="color: #800000;">"</span><span style="color: #800000;">0</span><span style="color: #800000;">"</span> Margin=<span style="color: #800000;">"</span><span style="color: #800000;">0</span><span style="color: #800000;">"</span>> <Grid VerticalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Center</span><span style="color: #800000;">"</span> HorizontalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Left</span><span style="color: #800000;">"</span>> <StackPanel Orientation=<span style="color: #800000;">"</span><span style="color: #800000;">Horizontal</span><span style="color: #800000;">"</span>> <ContentPresenter x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">Content</span><span style="color: #800000;">"</span> Margin=<span style="color: #800000;">"</span><span style="color: #800000;">17,0,0,0</span><span style="color: #800000;">"</span> ContentSource=<span style="color: #800000;">"</span><span style="color: #800000;">Header</span><span style="color: #800000;">"</span> HorizontalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Left</span><span style="color: #800000;">"</span> RecognizesAccessKey=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span> SnapsToDevicePixels=<span style="color: #800000;">"</span><span style="color: #800000;">{TemplateBinding SnapsToDevicePixels}</span><span style="color: #800000;">"</span> VerticalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Center</span><span style="color: #800000;">"</span>/> </StackPanel> </Grid> </Border> </Grid> <ControlTemplate.Triggers> <Trigger Property=<span style="color: #800000;">"</span><span style="color: #800000;">IsMouseOver</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">false</span><span style="color: #800000;">"</span>> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Foreground</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">#5c5c5c</span><span style="color: #800000;">"</span>/> </Trigger> <Trigger Property=<span style="color: #800000;">"</span><span style="color: #800000;">IsMouseOver</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">true</span><span style="color: #800000;">"</span>> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Foreground</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">#000000</span><span style="color: #800000;">"</span>/> </Trigger> <Trigger Property=<span style="color: #800000;">"</span><span style="color: #800000;">IsSelected</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">true</span><span style="color: #800000;">"</span>> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Panel.ZIndex</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span>/> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Background</span><span style="color: #800000;">"</span> TargetName=<span style="color: #800000;">"</span><span style="color: #800000;">Bd</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">#e6e7ea</span><span style="color: #800000;">"</span>/> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Foreground</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">#000000</span><span style="color: #800000;">"</span>/> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">BorderThickness</span><span style="color: #800000;">"</span> TargetName=<span style="color: #800000;">"</span><span style="color: #800000;">Bd</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">3,0,0,0</span><span style="color: #800000;">"</span>/> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">BorderBrush</span><span style="color: #800000;">"</span> TargetName=<span style="color: #800000;">"</span><span style="color: #800000;">Bd</span><span style="color: #800000;">"</span> Value=<span style="color: #800000;">"</span><span style="color: #800000;">#c62f2f</span><span style="color: #800000;">"</span>/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> "</span><span style="color: #800000;">{x:Type TabControl}</span><span style="color: #800000;">"</span>> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">OverridesDefaultStyle</span><span style="color: #800000;">"</span><span style="color: #000000;"> Value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span> /> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">TabStripPlacement</span><span style="color: #800000;">"</span><span style="color: #000000;"> Value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">Left</span><span style="color: #800000;">"</span> /> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">SnapsToDevicePixels</span><span style="color: #800000;">"</span><span style="color: #000000;"> Value</span>=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span> /> <Setter Property=<span style="color: #800000;">"</span><span style="color: #800000;">Template</span><span style="color: #800000;">"</span>> <Setter.Value> <ControlTemplate TargetType=<span style="color: #800000;">"</span><span style="color: #800000;">{x:Type local:itabcontrol}</span><span style="color: #800000;">"</span>> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width=<span style="color: #800000;">"</span><span style="color: #800000;">200</span><span style="color: #800000;">"</span> /> <ColumnDefinition Width=<span style="color: #800000;">"</span><span style="color: #800000;">*</span><span style="color: #800000;">"</span> /> </Grid.ColumnDefinitions> <!--可折叠菜单--> <Expander Header=<span style="color: #800000;">"</span><span style="color: #800000;">{TemplateBinding iTitle}</span><span style="color: #800000;">"</span> Grid.Column=<span style="color: #800000;">"</span><span style="color: #800000;">0</span><span style="color: #800000;">"</span>> <!--菜单项--> <TabPanel x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">HeaderPanel</span><span style="color: #800000;">"</span><span style="color: #000000;"> IsItemsHost</span>=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span><span style="color: #000000;"> KeyboardNavigation.TabIndex</span>=<span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;"> Background</span>=<span style="color: #800000;">"</span><span style="color: #800000;">Transparent</span><span style="color: #800000;">"</span> /> </Expander> <!--右侧内容区域--> <Border x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">Border</span><span style="color: #800000;">"</span><span style="color: #000000;"> Grid.Column</span>=<span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;"> KeyboardNavigation.TabNavigation</span>=<span style="color: #800000;">"</span><span style="color: #800000;">Local</span><span style="color: #800000;">"</span><span style="color: #000000;"> KeyboardNavigation.DirectionalNavigation</span>=<span style="color: #800000;">"</span><span style="color: #800000;">Contained</span><span style="color: #800000;">"</span><span style="color: #000000;"> KeyboardNavigation.TabIndex</span>=<span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span>> <ContentPresenter x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">PART_SelectedContentHost</span><span style="color: #800000;">"</span><span style="color: #000000;"> Margin</span>=<span style="color: #800000;">"</span><span style="color: #800000;">4</span><span style="color: #800000;">"</span><span style="color: #000000;"> ContentSource</span>=<span style="color: #800000;">"</span><span style="color: #800000;">SelectedContent</span><span style="color: #800000;">"</span> /> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter>
修改后你的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的用法,而在样式中是没办法这么用的,那该怎么去做呢?相信你看完代码就知道了。