[WP] ExpanderControl Personalizado

En este post compartire el código necesario para implementar un simple ExpanderControl. Ya dependera de tí agregar las animaciones que quieras para mejorar la experiencia de usuario.

XAML

Primero el XAML donde defino un par de estados visuales, un StackPanel y 2 Border que actuarán como contenedores.

<UserControl x:Class="XamlDev.Phone.UserControls.ExpanderControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">

<StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CustomGroup">
<VisualState x:Name="OpenedState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="brdExpandableContentContainer" Storyboard.TargetProperty="Visibility">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>Visible</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ClosedState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="brdExpandableContentContainer" Storyboard.TargetProperty="Visibility">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>Collapsed</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="brdContentContainter" Tap="brdContentContainter_Tap">

</Border>
<Border x:Name="brdExpandableContentContainer" >

</Border>
</StackPanel>
</UserControl>

C#

Luego registramos los DependencyProperty para el contenido, el contenido expandible y un flag que nos servira para ocultar o mostrar el contenido expandible.

    public partial class ExpanderControl : UserControl
{
public new UIElement Content
{
get { return (FrameworkElement)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}

public static readonly new DependencyProperty ContentProperty =
DependencyProperty.Register("Content", typeof(UIElement), typeof(ExpanderControl), new PropertyMetadata(OnContentChanged));

private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ExpanderControl)d).brdContentContainter.Child = (FrameworkElement)e.NewValue;
}

public FrameworkElement ExpandableContent
{
get { return (FrameworkElement)GetValue(ExpandableContentProperty); }
set { SetValue(ExpandableContentProperty, value); }
}

public static readonly DependencyProperty ExpandableContentProperty =
DependencyProperty.Register("ExpandableContent", typeof(FrameworkElement), typeof(ExpanderControl), new PropertyMetadata(OnExpandableContentChanged));

private static void OnExpandableContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ExpanderControl)d).brdExpandableContentContainer.Child = (FrameworkElement)e.NewValue;
}

public bool IsOpen
{
get { return (bool)GetValue(IsOpenProperty); }
set { SetValue(IsOpenProperty, value); }
}

public static readonly DependencyProperty IsOpenProperty =
DependencyProperty.Register("IsOpen", typeof(bool), typeof(ExpanderControl), new PropertyMetadata(false, OnIsOpenChanged));

private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
VisualStateManager.GoToState((ExpanderControl)d, "OpenedState", false);
else
VisualStateManager.GoToState((ExpanderControl)d, "ClosedState", false);
}

public ExpanderControl()
{
InitializeComponent();
VisualStateManager.GoToState(this, "ClosedState", false);
}

private void brdContentContainter_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
e.Handled = true;
this.IsOpen = !this.IsOpen;
}
}

¿Como usar?

Agregar el namespace del ExpanderControl, por ejemplo: xmlns:userControls=”clr-namespace:XamlDev.Phone.UserControls” y listo.


<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<userControls:ExpanderControl Grid.Row="1">
<userControls:ExpanderControl.Content>
<TextBlock Style="{StaticResource PhoneTextLargeStyle}" Text="Hazme Tap!"/>
</userControls:ExpanderControl.Content>
<userControls:ExpanderControl.ExpandableContent>
<TextBlock Style="{StaticResource PhoneTextLargeStyle}" Text="Hola! Soy el contenido expandible."/>
</userControls:ExpanderControl.ExpandableContent>
</userControls:ExpanderControl>
</Grid>

Agregue un comentario

Su dirección de correo no se hará público. Los campos requeridos están marcados *