This sample inherits the Expander control which is available in WPF. It support panel collapse in all the four directions (left, right, top and bottom).
public class CollapsiblePanel : Expander { static CollapsiblePanel() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CollapsiblePanel), new FrameworkPropertyMetadata(typeof(CollapsiblePanel))); } }
Here is the XAML for CollapsiblePanel
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:CollapsiblePanelDemo"> <local:MultiplyConverter x:Key="multiplyConverter" /> <Style x:Key="ExpanderHeaderFocusVisual"> <Setter Property="Control.Template"> <Setter.Value> <ControlTemplate> <Border> <Rectangle SnapsToDevicePixels="true" Margin="0" Stroke="Black" StrokeDashArray="1 2" StrokeThickness="1" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ExpanderUpHeaderStyle" TargetType="{x:Type ToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border Padding="{TemplateBinding Padding}"> <Grid Background="Transparent" SnapsToDevicePixels="False"> <Grid.LayoutTransform> <RotateTransform Angle="90"/> </Grid.LayoutTransform> <Path x:Name="trapazoid" Fill="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" HorizontalAlignment="Center" VerticalAlignment="Center"> <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigure StartPoint="0,0" > <PathFigure.Segments> <ArcSegment Size="25,25" RotationAngle="45" IsLargeArc="False" SweepDirection="Clockwise" Point="0,48"/> </PathFigure.Segments> </PathFigure > </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> <Path x:Name="arrow" Data="M 1,1.5 L 9,9 L 1,16 1, 1" HorizontalAlignment="Center" SnapsToDevicePixels="false" Fill="{Binding Path=BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" StrokeThickness="2" VerticalAlignment="Center"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Data" TargetName="arrow" Value="M 9,1 L 1,8 L 9,16, 9,1"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ExpanderLeftHeaderStyle" TargetType="{x:Type ToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border Padding="{TemplateBinding Padding}"> <Grid Background="Transparent" SnapsToDevicePixels="False"> <Path x:Name="trapazoid" Fill="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" HorizontalAlignment="Center" VerticalAlignment="Center"> <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigure StartPoint="0,0" > <PathFigure.Segments> <ArcSegment Size="25,25" RotationAngle="45" IsLargeArc="False" SweepDirection="Clockwise" Point="0,48"/> </PathFigure.Segments> </PathFigure > </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> <Path x:Name="arrow" Data="M 1,1.5 L 9,9 L 1,16 1, 1" HorizontalAlignment="Center" SnapsToDevicePixels="false" Fill="{Binding Path=BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" StrokeThickness="2" VerticalAlignment="Center"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Data" TargetName="arrow" Value="M 9,1 L 1,8 L 9,16, 9,1"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ExpanderRightHeaderStyle" TargetType="{x:Type ToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border Padding="{TemplateBinding Padding}"> <Grid Background="Transparent" SnapsToDevicePixels="False"> <Grid.LayoutTransform> <RotateTransform Angle="180"/> </Grid.LayoutTransform> <Path x:Name="trapazoid" Fill="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" HorizontalAlignment="Center" VerticalAlignment="Center"> <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigure StartPoint="0,0" > <PathFigure.Segments> <ArcSegment Size="25,25" RotationAngle="45" IsLargeArc="False" SweepDirection="Clockwise" Point="0,48"/> </PathFigure.Segments> </PathFigure > </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> <Path x:Name="arrow" Data="M 1,1.5 L 9,9 L 1,16 1, 1" HorizontalAlignment="Center" SnapsToDevicePixels="false" Fill="{Binding Path=BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" StrokeThickness="2" VerticalAlignment="Center"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Data" TargetName="arrow" Value="M 9,1 L 1,8 L 9,16, 9,1"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border Padding="{TemplateBinding Padding}"> <Grid Background="Transparent" SnapsToDevicePixels="False"> <Grid.LayoutTransform> <RotateTransform Angle="-90"/> </Grid.LayoutTransform> <Path x:Name="trapazoid" Fill="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" HorizontalAlignment="Center" VerticalAlignment="Center"> <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigure StartPoint="0,0" > <PathFigure.Segments> <ArcSegment Size="25,25" RotationAngle="45" IsLargeArc="False" SweepDirection="Clockwise" Point="0,48"/> </PathFigure.Segments> </PathFigure > </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> <Path x:Name="arrow" Data="M 1,1.5 L 9,9 L 1,16 1, 1" HorizontalAlignment="Center" SnapsToDevicePixels="false" Fill="{Binding Path=BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType=local:CollapsiblePanel}}" StrokeThickness="2" VerticalAlignment="Center"/> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Data" TargetName="arrow" Value="M 9,1 L 1,8 L 9,16, 9,1"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type local:CollapsiblePanel}"> <Setter Property="Background" Value="LightGray"/> <Setter Property="BorderBrush" Value="White"/> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Expander}"> <Border SnapsToDevicePixels="true"> <DockPanel> <ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="0" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> <Grid x:Name="ExpandSiteContainer" Visibility="Visible" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" DockPanel.Dock="Bottom" > <Grid.Tag> <sys:Double>0.0</sys:Double> </Grid.Tag> <ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden" > <ContentPresenter x:Name="ExpandSite" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" > </ContentPresenter> </ScrollViewer> </Grid> </DockPanel> </Border> <ControlTemplate.Triggers> <Trigger Property="IsExpanded" Value="true"> <Trigger.EnterActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName ="ExpandSiteContainer" Storyboard.TargetProperty ="Tag" To="1.0" Duration ="0:0:0.45" /> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName ="ExpandSiteContainer" Storyboard.TargetProperty ="Tag" To="0" Duration ="0:0:0.45"/> </Storyboard> </BeginStoryboard> </Trigger.ExitActions> </Trigger> <Trigger Property="ExpandDirection" Value="Down"> <Setter Property="Height" TargetName="ExpandSiteContainer"> <Setter.Value> <MultiBinding Converter="{StaticResource multiplyConverter}"> <Binding Path="ActualHeight" ElementName="ExpandSite"/> <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> </MultiBinding> </Setter.Value> </Setter> </Trigger> <Trigger Property="ExpandDirection" Value="Right"> <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/> <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/> <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderRightHeaderStyle}"/> <Setter Property="Width" TargetName="ExpandSiteContainer"> <Setter.Value> <MultiBinding Converter="{StaticResource multiplyConverter}"> <Binding Path="ActualWidth" ElementName="ExpandSite"/> <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> </MultiBinding> </Setter.Value> </Setter> </Trigger> <Trigger Property="ExpandDirection" Value="Up"> <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/> <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/> <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderUpHeaderStyle}"/> <Setter Property="Height" TargetName="ExpandSiteContainer"> <Setter.Value> <MultiBinding Converter="{StaticResource multiplyConverter}"> <Binding Path="ActualHeight" ElementName="ExpandSite"/> <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> </MultiBinding> </Setter.Value> </Setter> </Trigger> <Trigger Property="ExpandDirection" Value="Left"> <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/> <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Right"/> <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderLeftHeaderStyle}"/> <Setter Property="Width" TargetName="ExpandSiteContainer"> <Setter.Value> <MultiBinding Converter="{StaticResource multiplyConverter}"> <Binding Path="ActualWidth" ElementName="ExpandSite"/> <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> </MultiBinding> </Setter.Value> </Setter> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
Following is the example of using CollapsiblePanel control in WPF.
<my:CollapsiblePanel Grid.Row="2" Grid.Column="1" Header="Toolbar Demo" ExpandDirection="Down" x:Name="Expander2" BorderBrush="Yellow" Background="{StaticResource ToggleButtonBrush}" IsExpanded="False"> <my:CollapsiblePanel.Content> <Image Source="/CollapsiblePanelDemo;component/Images/Koala.jpg" Height="240" Stretch="Fill" /> </my:CollapsiblePanel.Content> </my:CollapsiblePanel>
You can download complete source code from following link
Download Source Code