[C#] Service Locator Pattern

Service Locator es un patrón creacional construido sobre el Principio de Inversión de Dependencias (DIP) el cual es ampliamente usado en la POO. En el siguiente video comparto una breve explicación de lo que comprende este patrón además de realizar ejemplos desde 0 de como podría ser implementada.

El código fuente del proyecto puede ser descargado aquí: http://1drv.ms/1mQIcPO

 

[Front End Web Dev] ¿Como mantener el footer siempre abajo?

¿A quién no le ha pasado este problema tan interesante? Tienes un super contenido con todo y animaciones, pero de pronto cuando no tienes mucho contenido el footer aparece casi por la mitad de la página. Revisas el body y los contenedores intentando asegurarte de que estén bien puesto los relative y absolute, pero aun asi parece no funcionar nada.

Lo bueno aquí es que no es brujería y sí tiene solución. El problema es simplemente el orden, por eso aquí compartiré la forma en que me funciónó.

HTML

Empecemos definiendo un esquema básico para nuestra página.

CSS

Y por último el CSS que hará la mágia.

UPDATE 2016-02-17

HTML

CSS

[WP8] ListBox’s SelectedItem Style

En este post explicaré como modificar de forma básica el estilo del contenedor de un ítem en un ListBox.

Paso 1

Definimos un ListBox y en plantillas adicionales buscamos editar el estilo del contenedor (ItemContainerStyle).

Paso 2

Ahora definimos algunos valores en el estilo que acabamos de crear, luego buscamos dentro la propiedad Template el grupo visual que coresponda a SelectionStates y modificamos el VisualState llamado “Selected”.


<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Foreground" Value="Purple"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentContainer"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="Purple"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Paso 3

Finalmente modificamos el ListBox para que use el estilo que acabamos de crear. Para tener data yo me ayude partiendo de la plantilla Databound App.


<ListBox Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionMode="Single" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="{StaticResource PhoneTouchTargetOverhang}">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeExtraLarge}" FontFamily="{StaticResource PhoneFontFamilySemiLight}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Y eso es todo amigos

[WP8] PhotoChooserTask & CameraCaptureTask

Estas clases nos permitirán seleccionar una foto desde nuestra librería de medios o tomar una nueva foto respectivamente.

A continuación un ejemplo muy sencillo de como usarlos para mostrar la foto seleccionada o capturada en un elemento Image.

Paso 1

Definir el XAML del elemento Image y los botones de la barra de la aplicación.


<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid x:Name="ContentPanel">
<Image x:Name="image"/>
</Grid>
</Grid>

<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar>
<shell:ApplicationBar.Buttons>
<shell:ApplicationBarIconButton IconUri="/Assets/AppBar/folder.png" Text="select photo" Click="SelectPhotoIconButton_Click"/>
<shell:ApplicationBarIconButton IconUri="/Assets/AppBar/feature.camera.png" Text="take photo" Click="TakePhotoIconButton_Click"/>
</shell:ApplicationBar.Buttons>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Paso 2

En el code-behind manejamos los eventos de los ApplicationBarIconButton de la siguiente manera.


private void SelectPhotoIconButton_Click(object sender, EventArgs e)
{
var photoChooserTask = new PhotoChooserTask();
photoChooserTask.ShowCamera = true;
photoChooserTask.Completed += photoChooserTask_Completed;
photoChooserTask.Show();
}

private void TakePhotoIconButton_Click(object sender, EventArgs e)
{
var cameraCaptureTask = new CameraCaptureTask();
cameraCaptureTask.Completed += photoChooserTask_Completed;
cameraCaptureTask.Show();
}

private void photoChooserTask_Completed(object sender, PhotoResult e)
{
if(e.TaskResult == TaskResult.OK)
{
var bitmapImage = new BitmapImage();
bitmapImage.SetSource(e.ChosenPhoto);

this.image.Source = bitmapImage;
}
}

Y ya esta todo, no olvidarse de activar el ID_CAP_ISV_CAMERA en Capabilites del WMAppManifest.xml.

[WP8] ¿Cómo obtener el ancho de banda?

1. Agregamos las referencias necesarias:

using Microsoft.Phone.Net.NetworkInformation;

2. Creamos una lista para visualizar la información:

            <ItemsControl x:Name="lbNetworkInterfaces">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="27">
<TextBlock Text="{Binding Bandwidth, StringFormat='Bandwidth: {0}'}" />
<TextBlock Text="{Binding Characteristics, StringFormat='Characteristics: {0}'}" />
<TextBlock Text="{Binding Description, StringFormat='Description: {0}'}"/>
<TextBlock Text="{Binding InterfaceName, StringFormat='InterfaceName: {0}'}"/>
<TextBlock Text="{Binding InterfaceState, StringFormat='InterfaceState: {0}'}"/>
<TextBlock Text="{Binding InterfaceSubtype, StringFormat='InterfaceSubtype: {0}'}"/>
<TextBlock Text="{Binding InterfaceType, StringFormat='InterfaceType: {0}'}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

3. Finalmente llenamos la lista con el detalle de las interfaces de red:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.lbNetworkInterfaces.ItemsSource = new NetworkInterfaceList();
}

[MVVM] InstanceResolver

En este post compartiré como implementar de manera muy básica un InstanceResolver para clases con un constructor sin sobrecargas.

InstanceResolver.cs


public class InstanceResolver
{
public static readonly InstanceResolver Default = new InstanceResolver();

private InstanceResolver() { }

private readonly IDictionary<Type, Type> TypeMap = new Dictionary<Type, Type>();
private readonly IDictionary<Type, object> Instances = new Dictionary<Type, object>();

public T Resolve<T>()
{
return (T)Resolve(typeof(T));
}

public void Register<TFrom>()
{
TypeMap.Add(typeof(TFrom), typeof(TFrom));
}

public void Register<TFrom, TTo>()
{
TypeMap.Add(typeof(TFrom), typeof(TTo));
}

private object Resolve(Type type)
{
try
{
object resolvedType = null;

if (Instances.ContainsKey(type))
{
resolvedType = Instances[type];
}
else
{
resolvedType = Activator.CreateInstance(TypeMap[type]);
Instances.Add(type, resolvedType);
}

return resolvedType;
}
catch (Exception)
{
throw new Exception(string.Format("Could not resolve type {0}", type.FullName));
}
}
}

¿Como usar?


public class ViewModelLocator
{
public ViewModelLocator()
{
InstanceResolver.Default.Register<LoginVM>();
InstanceResolver.Default.Register<UsuarioVM>();
}

public LoginVM LoginVM
{
get
{
return InstanceResolver.Default.Resolve<LoginVM>();
}
}

public UsuarioVM UsuarioVM
{
get
{
return InstanceResolver.Default.Resolve<UsuarioVM>();
}
}
}

[WP8] Datos y Comunicacion

Almacenar, enviar y recibir datos son actividades fundamental en los sistemas de información, por ello en este módulo hablaremos de como trabajar con el almacenamiento de datos local en Windows Phone, además de demostrar con una serie de ejemplos básicos como trabajar en una arquitectura REST usando la notación JSON que es la codificación más usada en esta arquitectura. PDT: JSON no es REST, es solo la codificación más usada, existen otras como por ejemplo POX.

Source Code: Xaml Development Codeplex

[WP8] Silverlight para Windows Phone 8 (Parte II)

Silverlight es una poderosa plataforma de desarrollo para crear aplicaciones web y mobil que sean capaces de brindar una gran experiencia de usuario. En este vídeo veremos todo lo que nos ofrece Silverlight para el desarrollo de aplicaciones en Windows Phone 8 con ayuda de varios ejemplos.

Source Code: Xaml Development Codeplex

[MVVM] RelayCommand

A continuación comparto una implementación del RelayCommand que estoy usando para trabajar con MVVM y PCL (Portable Class Library).

IRelayCommand.cs


public interface IRelayCommand : ICommand
{
void RaiseCanExecuteChanged();
}

RelayCommand class


public class RelayCommand : IRelayCommand
{
#region Fields

private readonly Action _execute;
private readonly Func<bool> _canExecute;

#endregion Fields

#region Constructors

public RelayCommand(Action execute)
: this(execute, null)
{
}

public RelayCommand(Action execute, Func<bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}

#endregion Constructors

#region ICommand Members

public bool CanExecute(object parameter)
{
return null == _canExecute ? true : _canExecute();
}

public void Execute(object parameter)
{
_execute();
}

public void RaiseCanExecuteChanged()
{
if (null != this.CanExecuteChanged)
this.CanExecuteChanged.Invoke(this, EventArgs.Empty);
}

public event EventHandler CanExecuteChanged;

#endregion ICommand Members
}

RelayCommand<T> class


public class RelayCommand<T> : IRelayCommand
{
#region Fields

private readonly Action<T> _execute;
private readonly Func<T, bool> _canExecute;

#endregion Fields

#region Constructors

public RelayCommand(Action<T> execute)
: this(execute, null)
{
}

public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}

#endregion Constructors

#region ICommand Members

public bool CanExecute(object parameter)
{
parameter = null == parameter ? default(T) : parameter;
return null == _canExecute ? true : _canExecute((T)parameter);
}

public void Execute(object parameter)
{
parameter = null == parameter ? default(T) : parameter;
_execute((T)parameter);
}

public void RaiseCanExecuteChanged()
{
if (null != this.CanExecuteChanged)
this.CanExecuteChanged.Invoke(this, EventArgs.Empty);
}

public event EventHandler CanExecuteChanged;

#endregion ICommand Members
}

¿Como usar?


#region Command Members

private RelayCommand aceptarCommand;

#endregion Command Members

#region Command Properties

public RelayCommand AceptarCommand
{
get
{
if (null == aceptarCommand)
aceptarCommand = new RelayCommand(AceptarExecute, AceptarCanExecute);

return aceptarCommand;
}
}

#endregion Command Properties

#region Command Methods

private bool AceptarCanExecute()
{
return true;
}

private void AceptarExecute()
{
}

#endregion Command Methods

[WP] Codigos QR

Hace poco me tope con la oportunidad de implementar una funcionalidad que me permitiera leer Códigos QR desde mi Windows Phone. Y sinceramente fue más sencillo de lo que esparaba gracias a una librería que encontré :). Para probarlo compartiré los pasos a seguir:

Paso 1

Usando NuGet Packages (haciendo click derecho sobre el Proyecto o la carpeta References -> Manage NuGet Packages…) descargamos la libreria ZXing.WP7 (la cual también es válida para WP8).

Paso 2

Definir la clase PhotoCameraLuminanceSource de la siguiente manera:


public class PhotoCameraLuminanceSource : LuminanceSource
{
public byte[] PreviewBufferY { get; private set; }

public PhotoCameraLuminanceSource(int width, int height) : base(width, height)
{
PreviewBufferY = new byte[width * height];
}

public override sbyte[] Matrix
{
get { return (sbyte[])(Array)PreviewBufferY; }
}

public override sbyte[] getRow(int y, sbyte[] row)
{
if (row == null || row.Length < Width)
{
row = new sbyte[Width];
}

for (int i = 0; i < Height; i++)
row[i] = (sbyte)PreviewBufferY[i * Width + y];

return row;
}
}

Paso 3

Definir el XAML y el CSharp de la página (en mi caso la llame QRReaderPage) desde donde capturaremos el Código QR usando la cámara. En caso hagamos esto usando WP8 no hay que olvidarse de activar el ID_CAP_ISV_CAMERA en Capabilites del WMAppManifest.xml.

XAML


<Grid x:Name="LayoutRoot" Background="Transparent">
<Rectangle>
<Rectangle.Fill>
<VideoBrush x:Name="videoBrush" >
<VideoBrush.RelativeTransform>
<CompositeTransform x:Name="compositeTransform" CenterX="0.5" CenterY="0.5"/>
</VideoBrush.RelativeTransform>
</VideoBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>

CSharp


public partial class QRReaderPage : PhoneApplicationPage
{
private PhotoCamera photoCamera;
private readonly DispatcherTimer dispatcherTimer = new DispatcherTimer();
private QRCodeReader codeReader;

public QRReaderPage()
{
InitializeComponent();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
photoCamera = new PhotoCamera(CameraType.Primary);
photoCamera.Initialized += (s, a) =>
{
codeReader = new QRCodeReader(); ;
Dispatcher.BeginInvoke(() => { compositeTransform.Rotation = photoCamera.Orientation; });
};
videoBrush.SetSource(photoCamera);

dispatcherTimer.Interval = TimeSpan.FromMilliseconds(250);
dispatcherTimer.Tick += (o, arg) => ScanPreviewBuffer();
dispatcherTimer.Start();
base.OnNavigatedTo(e);
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
dispatcherTimer.Stop();
}

private void ScanPreviewBuffer()
{
try
{
// crear un QRCodeReader
int width = Convert.ToInt32(photoCamera.PreviewResolution.Width);
int height = Convert.ToInt32(photoCamera.PreviewResolution.Height);
PhotoCameraLuminanceSource _luminance = new PhotoCameraLuminanceSource(width, height);
photoCamera.GetPreviewBufferY(_luminance.PreviewBufferY);
// crear un bitmap
var binBitmap = new com.google.zxing.BinaryBitmap(new HybridBinarizer(_luminance));
// detectar y decodificar el bitmap
var result = codeReader.decode(binBitmap);

// hacer lo que queramos con el result
NavigationService.Navigate(new Uri(string.Format("/Views/QRReaderResultPage.xaml?qrcode={0}", result.Text), UriKind.RelativeOrAbsolute));
}
catch { }
}
}

Y listo eso es lo unico que hay que hacer :)!