GeekyTool [BETA] - Novedades en v.1.0.0.1

Hola geeks! No paramos de desarrollar nuestro toolkit para aplicaciones universales de la plataforma de Windows. Antes de nada, hemos optado en cambiarle el nombre de GeekyTheroy.Toolkit a GeekyTool. Nos parece el momento de cambiar el nombre, y además añadirle el hashtag de #madeInSpain.

¿Qué ha cambiado?

Vamos empezando con las novedades que traemos con la versión 1.0.0.1. NOTA: Si sentís curiosidad, siempre podéis seguir el proyecto en Github y ver las novedades que están implementadas, que se van a implementar y cuando. Además podéis vosotros mismos añadir nuevos features que lo aceptamos e lo proyectaremos para una release.

GeekyHelper

En la clase GeekyHelper.cs, puedes encontrar todos los métodos útiles que necesites para el desarrollo. Si ves que falta una, estaremos encantados de un pull request. Por ahora tenemos los siguientes métodos:

  • ExtractFirstImageFromHtml: extrae la primera imagen por regex de un html.
  • ExtractAllImagesFromHtml: extrae todas las imágenes por regex de un html.
  • GetBrushColorFromHexa: Convierte un color expresado en hexadecimal con tipo string a un SolidColorBrush.
  • GetColorFromHexa: Convierte un color expresado en hexadecimal con tipo string a un Color.
  • ValidFeedUri: Valida si un determinado string es una Uri.

VariableGridView

VariableGridView es una extensión del control GridView que nos permite establecer el tamaño que queramos de cada GridViewItem mediante nuestro interfaceIResizable. IResizable, está constituido por ColSpan y RowSpan, quienes establecemos en el ColumnSpanProperty y RowSpanProperty de nuestro GridView.

Muy bien, y... ¿cómo lo uso?

Cuando estemos declarando un modelo para la aplicación. El modelo que va a hacer uso de una GridView, debe implementar nuestro interfaz IResizable. public class FeedItem : IResizable { public string Title { get; set; } public string Author { get; set; } public string Content { get; set; } public DateTime PubDate { get; set; } public string PubDateShow { get; set; } public string ImageUrl { get; set; } public Uri Link { get; set; } public MenuItem BlogName { get; set; } public SyndicationFormat Format { get; set; } // IResizable public int ColSpan { get; set; } public int RowSpan { get; set; } } Ahora solo nos falta "bindear" dicho modelo a nuestro VariableGridView y tener las propiedades ColSpan y RowSpan con valores. Así de fácil. <geekyControls:VariableGridView x:Name="VariableGridView" Background="{StaticResource Gray300}" ItemsSource="{Binding Feeds}" SelectedItem="{Binding Feed, Mode=TwoWay}" ItemTemplate="{StaticResource StarFeedItemDataTemplate}"> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> <Setter Property="VerticalContentAlignment" Value="Stretch" /> </Style> </GridView.ItemContainerStyle> <GridView.ItemsPanel> <ItemsPanelTemplate> <VariableSizedWrapGrid Background="{StaticResource Gray300}" Orientation="Horizontal" ItemHeight="240" ItemWidth="{Binding VariableSizedGrid_Width}" /> </ItemsPanelTemplate> </GridView.ItemsPanel> </geekyControls:VariableGridView>

Converters

También añadimos más converters. Los que a día de hoy están disponibles son:

  • BooleanNegationConverter: Nos devuelve el valor inverso del booleano.
  • BooleanToInverseVisibilityConverter: Nos devuelve la visibilidad inversa del valor del booleano.
  • BooleanToVisibilityConverter: Nos devuelve la visibilidad del valor del booleano.
  • DoubleToIntConverter: Convierte un double en un int.
  • DoubleToStringFromatConverter: Convierte un double en un string con formato (N, C, C0, G,...)
  • RadioButtonCheckedConverter: Bindea multiple radiobuttons a una propiedad con carácter nullable. Tenemos un articulo explicando cómo utilizar éste converter.
  • StringToColorConverter: Utiliza nuestro GeekyHelper.GetColorFromHexa para tenerlo también como converter.
  • StringToSolidColorBrushConverter: Utiliza nuestro GeekyHelper.GetBrushColorFromHexa para tenerlo también como conveter.
  • ToUpperConverter: Convierte el texto en mayúsculas.

Extensiones

Tenemos un par de extensiones que podrían ser de gran utilidad. Vamos a verlo cuales son!

Helpers

Tenemos implementada un helper de TitleBar. Nos ayuda manejar fácilmente los colores del TitleBar.

Muy bien, y... ¿cómo lo uso?

Simplemente declaramos en el MainPage las siguientes líneas de código. helpers:TitleBar.BackgroundColor="{Binding MenuItem.Brush, Converter={StaticResource StringToColorConverter}}" helpers:TitleBar.ForegroundColor="White" helpers:TitleBar.ButtonBackgroundColor="{Binding MenuItem.Brush, Converter={StaticResource StringToColorConverter}}" helpers:TitleBar.ButtonForegroundColor="White" Podemos observar, que estamos utilizando el converter StringToColorConverter para pasar de la propiedad Brush que en este caso es un string a un tipo color.

Logging Manager

También implementamos un manejado de logs para que ningún error se pierda cuando se esté desarrollando una aplicación.

Muy bien, y... ¿cómo lo uso?

Declaramos en el App.xaml.cs, en el método OnLaunched, en el siguiente bloque, las siguientes sentencias: if (rootFrame.Content == null) { EventListener informationListener = new StorageFileEventListener("GeekyInfo"); informationListener.EnableEvents(MetroEventSource.Log, EventLevel.Informational); // When the navigation stack isn't restored navigate to the first page, // configuring the new page by passing required information as a navigation // parameter rootFrame.Navigate(typeof(ShellView), e.Arguments); } Acabamos de suscribirnos a GeekyInfo.log con un nivel de evento "Informational". Esto significa, que todos los log de tipo "Info" se escribirán en GeekyInfo.log. Podemos crear tantas como EventLevel haya. Ahora solo nos falta escribir un error, y se de la siguiente manera: MetroEventSource.Log.Info("Esto es un error informativo!! :) ");

Models

Con Windows 10, salió el tan famoso SplitView. Para ello, hemos creado una interfaz de modelo para que podáis extender de ella. Tiene lo más básico para construir una SplitViewinterface IMenuItem { string Icon { get; set; } string Title { get; set; } Type View { get; set; } ICommand Command { get; set; } } También tenemos una implementación de dicho modelo, si os sirve y queréis utilizarlo. public class MenuItem : IMenuItem { public string Icon { get; set; } public string Title { get; set; } public Type View { get; set; } public ICommand Command { get; set; } public string Brush { get; set; } public string Url { get; set; } }

Services

Implementamos ISplitterMenuService para manejar más cómodamente los items del SplitterView. Con este servicio podemos, registrar una colección, añadir y quitar tanto un ítem como una colección de items. public interface ISplitterMenuService { void RegisterCollection(ObservableCollection<MenuItem> menuItemsCollection); void AddItems(IEnumerable<MenuItem> menuItemsCollection); void AddItem(MenuItem menuItem); void RemoveItems(IEnumerable<MenuItem> menuItemsCollection); void RemoveItem(MenuItem menuItem); }

Muy bien, y... ¿cómo lo uso?

Para ello, vamos a implementar una propiedad del servicio. private ISplitterMenuService splitterMenuService; protected ISplitterMenuService SplitterMenuService { get { if (splitterMenuService == null) { splitterMenuService = new SplitterMenuService(); if (menuItems == null) menuItems = new ObservableCollection<MenuItem>(); splitterMenuService.RegisterCollection(menuItems); } return splitterMenuService; } } Y una vez que lo tengamos implementado, ahora solo nos hace falta rellenar nuestro servicio con datos y es tan sencillo como esto: var items = new List<MenuItem>() { new MenuItem { Icon = "ms-appx:///Assets/Icons/Dashboard.png", Title = "Portada", Brush = "#212121", View = typeof (MainView) }, new MenuItem { Icon = "ms-appx:///Assets/Geeky/geeky_theory_icon_round.png", Title = "Geeky Theory", Brush = "#1ABB9C", Url = "http://geekytheory.com/feed/", View = typeof (MainView) }, new MenuItem { Icon = "ms-appx:///Assets/Geeky/geeky_juegos_icon_round.png", Title = "Geeky Juegos", Brush = "#FF6C60", Url = "http://geekyjuegos.com/feed/", View = typeof (MainView) }, new MenuItem { Icon = "ms-appx:///Assets/Icons/Category.png", Title = "Categorías", } }; SplitterMenuService.AddItems(items);

ViewModels

Y por último, hemos separado los ViewModels para utilizarlo en un SplitterView y otro para los demás ViewModels:

ViewModelBase
  • Implementa la interfaz INotifyPropertyChanged.
  • Contiene la propiedad bool IsBusy para facilitar a cada página cuando esté haciendo una llamada asíncrona.
  • VariableSizedGrid_Width: Tenemos una propiedad Width que será calculada cada vez que la App cambie de tamaño. Nos sirve para adaptar los GridViewItems al nuevo tamaño.
  • ViewWidth: Será el width real en cada cambio de tamaño de la App, donde VariableSizedGrid_Width, será una división por n (determinada por el usuario). Así por ejemplo, si el ViewWidth es de 800px, y queremos dividir el GridView en 4, el VariableSizedGrid_Width será de 200px.
  • GetCalculatedVariableSize(double width, int n): aquí podemos establecer el divisor mencionado arriba.
  • SetVisibilityOfNavigationBack(): Aquí está declarado la visibilidad del botón atrás del sistema.
  • SystemNavigationManager_BackRequested: es el evento que tenemos que disparar cuando queremos navegar con el botón atrás.
  • AppView_SizeChange: es el metodo que tenemos que registrar a cada codebehind de la pagina que queremos que detecte un cambio de tamaño e actualice ViewWidth y VariableSizedGrid_Width.

public abstract class ViewModelBase : INotifyPropertyChanged { private Frame appFrame; private bool isBusy; private double variableSizedGrid_Width; private double viewWidth; public Frame AppFrame => appFrame; public bool IsBusy {...} public double VariableSizedGrid_Width {...} public double ViewWidth {...} public abstract Task OnNavigatedFrom(NavigationEventArgs e); public abstract Task OnNavigatedTo(NavigationEventArgs e); public virtual void GetCalculatedVariableSize(double width, int n) {...} public virtual void SetVisibilityOfNavigationBack() {...} public virtual void SystemNavigationManager_BackRequested(object sender, BackRequestedEventArgs e) {...} public virtual void AppView_SizeChanged(object sender, SizeChangedEventArgs e) {...} public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {...} internal void SetAppFrame(Frame viewFrame) {...} }

SplitterViewModelBase
  • Implementa ViewModelBase.
  • SplitViewFrame: Tenemos el SplitViewFrame declarado.
  • IsPaneOpen: para controlar el estado del SplitView.
  • MenuItems: La colección para almacenar todos los items del SplitView.
  • MenuItem: Es el item seleccionado.
  • SplitterMenuService: Es el servicio anteriormente explicado. Con él podemos añadir y quitar los itemas.
  • SetVisibilityOfNavigationBack(): Es la nueva implementación del SetVisibilityOfNavigationBack del ViewModelBase.
  • SystemNavigationManager_BackRequested: Es la nueva implementación del SystemNavigationManager_BackRequested del ViewModelBase.
  • PerformNavigationCommandDelegate: Éste método tenemos que implementarlo donde meteremos la lógica de navegación de cada MenuItem.

public abstract class SplitterViewModelBase : ViewModelBase { private bool isPaneOpen; private Frame splitViewFrame; private ObservableCollection<MenuItem> menuItems; private MenuItem menuItem; private ISplitterMenuService splitterMenuService; public Frame SplitViewFrame => splitViewFrame; public bool IsPaneOpen {...} public ObservableCollection<MenuItem> MenuItems {...} public MenuItem MenuItem {...} protected ISplitterMenuService SplitterMenuService {...} public new virtual void SetVisibilityOfNavigationBack() {...} public new virtual void SystemNavigationManager_BackRequested(object sender, BackRequestedEventArgs e) {...} internal void SetSplitFrame(Frame viewFrame) {...} protected abstract void PerformNavigationCommandDelegate(MenuItem item); } Nota: Estamos desarrollando un lector de noticias de GeekyBlogs donde utilizamos la mayoría de la features de GeekyTool. ¡Síguenos y echa un vistazo para descubrir el potencial que tiene! Si os ha gustado no os lo quedéis para vosotros. ¡Compartid!

Happy Coding y nos vemos en más publicaciones!