[WINRT] AppBar autoocultable

Continuando un poco con la estela del post anterior en el que hablaba de los Behaviors, en este vamos a ver como agregar una funcionalidad que puede ser bastante interesante en nuestras aplicaciones para Windows Store.

Lo que vamos a abordar, es como auto ocultar la barra de aplicación, según el tiempo deseado. Para resolver esta problematica vamos a agregar dos Dependency Properties a los controles de tipo AppBar:

– La primera una propiedad de tipo Booleana que será la encargada de indicar si se aplica el auto cierre o no. Dentro del establecimiento de esta propiedad vamos a agregar los manejadores de eventos para cuando se abrá la AppBar y cuando entre y salga el cursor dentro de ella (para parar el contador si el cursor está dentro de la AppBar)

– La segunda una propiedad de tipo Integer que servirá para expresar en segundos cuando se va a llevar a cabo el cierre de la AppBar. El valor por defecto de esta propiedad va a ser 5.

Al lio:

   1: public class AppBarExtensions

   2:     {

   3:         public static AppBar appBar;

   4:  

   5:         public static readonly DependencyProperty AutoCloseTimeProperty = DependencyProperty.RegisterAttached("AutoCloseTime", typeof(int), typeof(AppBarExtensions),

   6:             new PropertyMetadata(5));

   7:  

   8:         public static int GetAutoCloseTime(UIElement element)

   9:         {

  10:             return (int)element.GetValue(AutoCloseTimeProperty);

  11:         }

  12:  

  13:         public static void SetAutoCloseTime(UIElement element, int value)

  14:         {

  15:             element.SetValue(AutoCloseTimeProperty, value);

  16:         }

  17:  

  18:         public static readonly DependencyProperty AutoCloseProperty = DependencyProperty.RegisterAttached("AutoClose", typeof(bool), typeof(AppBarExtensions),

  19:        new PropertyMetadata(DependencyProperty.UnsetValue,

  20:        (o, e) =>

  21:        {

  22:            var control = o as AppBar;

  23:  

  24:            appBar = control;

  25:            if (control != null)

  26:            {

  27:                if ((bool)e.NewValue)

  28:                {

  29:                    control.Opened += AppBarOpened;

  30:                    control.PointerEntered += control_PointerEntered;

  31:                    control.PointerExited += control_PointerExited;

  32:                }

  33:                else

  34:                {

  35:                    control.Opened -= AppBarOpened;

  36:                    control.PointerEntered -= control_PointerEntered;

  37:                    control.PointerExited -= control_PointerExited;

  38:                }

  39:            }

  40:        }));

  41:  

  42:         static void control_PointerExited(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)

  43:         {

  44:             timer.Tick += timer_Tick;

  45:             timer.Start();

  46:             Elapsed = 1;

  47:         }

  48:  

  49:         static void control_PointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)

  50:         {

  51:             timer.Stop();

  52:             timer.Tick -= timer_Tick;

  53:             Elapsed = 1;

  54:         }

  55:  

  56:         private static DispatcherTimer timer;

  57:  

  58:         private static int Elapsed = 1;

  59:  

  60:         static void AppBarOpened(object sender, object e)

  61:         {

  62:             timer = new DispatcherTimer();

  63:             timer.Interval = TimeSpan.FromSeconds(1);

  64:             timer.Tick += timer_Tick;

  65:             timer.Start();

  66:         }

  67:  

  68:         static void timer_Tick(object sender, object e)

  69:         {

  70:             if (Elapsed == GetAutoCloseTime((UIElement)appBar))

  71:             {

  72:                

  73:                 Elapsed = 1;

  74:                 appBar.IsOpen = false;

  75:                 timer.Stop();

  76:             }

  77:             else

  78:                 Elapsed++;

  79:         }

  80:         public static bool GetAutoClose(UIElement element)

  81:         {

  82:             return (bool)element.GetValue(AutoCloseProperty);

  83:         }

  84:         public static void SetAutoClose(UIElement element, bool value)

  85:         {

  86:             element.SetValue(AutoCloseProperty, value);

  87:         }

  88:     }

Del mismo modo que en el ejemplo del post anterior, vamos a ver como usarlo dentro de nuestro código:

 

   1: xmlns:appbar="using:AppBarExtensions"

De esa manera podremos empezar a utilizarlo en nuestra AppBar:

   1: <AppBar x:Name="appbar" appbar:AppBarExtensions.AutoClose="True" appbar:AppBarExtensions.AutoCloseTime="3" />

Espero que os resulte de utilidad.

 

Saludos!

[WINRT] Behaviors

El patrón de diseño mas utilizado a la hora de crear aplicaciones con WPF, Silverlight o Windows 8 es MVVM (Model – View – ViewModel).

 

Aunque no voy a entrar a la explicación de este patrón voy a hablar de algo relacionado con él.

 

Uno de los objetivos de este patrón es ayudarnos a mantener nuestro código lo mejor estructurado posible.

 

En este post me voy a centrar en explicar una problemática existente dentro de Windows 8 y mas concretamente en las desarrolladas con XAML.

El problema radica en la no existencia de triggers que si existian en WPF, como podían ser EventTrigger que se producian al lanzarse un evento.

Debido a ello, vamos a ver como podemos extender los controles de WINRT, para que en lugar de utilizar los eventos desde el código de nuestra página / control, enlacemos a través de un Binding con una propiedad ICommand de nuestro modelo.

Para poder hacer esto, sera necesario definir una Dependency Property. Para el ejemplo concreto vamos a ver como capturar una tecla pulsada por ejemplo en un control de tipo TextBox:

   1: public class PageKeyPressBehavior

   2: {

   3:     public static readonly DependencyProperty KeyDownCommandProperty = DependencyProperty.RegisterAttached("KeyDownCommand", typeof(ICommand), typeof(PageKeyPressBehavior),

   4:                 new PropertyMetadata(DependencyProperty.UnsetValue,

   5:                     (o, e) =>

   6:                     {

   7:                         var textbox = o as TextBox;

   8:                         if (textbox != null)

   9:                         {

  10:                             if (e.NewValue != null && e.OldValue == null)

  11:                                 textbox.KeyDown +=  KeyDownEvent;

  12:                             else if (e.NewValue == null && e.OldValue != null)

  13:                                 textbox.KeyDown -= textbox_KeyDownEvent;

  14:                         }

  15:                     }));

  16:  

  17:             public static ICommand GetIntroButtonCommand(UIElement element)

  18:             {

  19:                 return (ICommand)element.GetValue(IntroButtonCommandProperty);

  20:             }

  21:  

  22:             public static void SetIntroButtonCommand(UIElement element, ICommand value)

  23:             {

  24:                 element.SetValue(IntroButtonCommandProperty, value);

  25:             }

  26:  

  27:             static void KeyDownEvent(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)

  28:             {

  29:                     var textbox = sender as TextBox;

  30:                     if (textbox != null)

  31:                     {

  32:                         ICommand cmd = GetIntroButtonCommand(textbox);

  33:                         if (cmd != null)

  34:                             cmd.Execute(e.Key.ToString());

  35:                        

  36:                     }   

  37:             }

  38: }

En el código del ejemplo lo que hacemos es registrar una propiedad en los controles de tipo TextBox, y agregamos el manejador de eventos para controlar el evento KeyDown. Dentro de dicho evento lo que haremos será invocar al valor de nuestra Dependency Property.

 

Bien, ahora como utilizamos esto dentro de nuestra pagina:

1) Lo primero será agregar el namespace donde está alojada la clase que incluye nuestra Dependency Property:

   1: xmlns:be="using:MyApp.Behaviors"

2) Utilizarla dentro de nuestro TextBox:

   1: <TextBox be:KeyDownCommand="{Binding MyKeyDownCommand}" />

 

Con esto ya trendriamos enlazado nuestro ViewModel y nuestra Vista sin tener que capturar los eventos desde el propio Code Behind.

 

Espero que os sea de utilidad.

 

Saludos!