1. 程式人生 > >C# WPF 左側選單右側內容佈局效果實現

C# WPF 左側選單右側內容佈局效果實現

原文: 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="300" d:DesignWidth="300"> <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="0" Value="{x:Static Visibility.Hidden}" /> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ExpandededArrow"> <DiscreteObjectKeyFrame KeyTime="0" 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="0" /> </Grid.RowDefinitions> <Border MinHeight="32" x:Name="Border" Grid.Row="0" > <Grid VerticalAlignment="Center"> <ContentPresenter Margin="4" ContentSource="Header" RecognizesAccessKey="True" /> <ToggleButton Background="Transparent" Width="{Binding ElementName=Border,Path=ActualWidth}" Panel.ZIndex="1" OverridesDefaultStyle="True" Template="{StaticResource ExpanderToggleButton}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"> </ToggleButton> </Grid> </Border> <Border x:Name="Content" Grid.Row="1" > <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="199" MinHeight="32" x:Name="Bd" CornerRadius="0" Background="Transparent" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="3,0,0,0" Padding="0" Margin="0"> <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="1"/> <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="200" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <!--可摺疊選單--> <Expander Header="{TemplateBinding iTitle}" Grid.Column="0"> <!--選單項--> <TabPanel x:Name="HeaderPanel" IsItemsHost="True" KeyboardNavigation.TabIndex="1" Background="Transparent" /> </Expander> <!--右側內容區域--> <Border x:Name="Border" Grid.Column="1" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2"> <ContentPresenter x:Name="PART_SelectedContentHost" Margin="4" 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的用法,而在樣式中是沒辦法這麼用的,那該怎麼去做呢?相信你看完程式碼就知道了。

 

專案下載:

點我下載