[WPF] Toolkit’s AutoCompleteBox

Hoy aprenderemos como usar el AutoCompleteBox en WPF con unos cuantos pasos.

WPF Toolkit

Luego de crear nuestro proyecto WPF tenemos que agregar el WPF Toolkit, si tienes los binarios genial sino puedes hacerlo usando Nuget.

C#

Para este ejemplo he tenido que crear un par de clases:

using System;

namespace AutoCompleteBoxWPF.Models
{
public class Client
{
public int Id { get; set; }

public string Name { get; set; }

public DateTime AffiliationDate { get; set; }

public override string ToString()
{
return string.Format("{0} - {1}", Name, AffiliationDate);
}
}
}
using AutoCompleteBoxWPF.Models;
using System;
using System.Collections.Generic;

namespace AutoCompleteBoxWPF.Services
{
public class ApplicationService
{
public List<Client> ReadAll()
{
var random = new Random();
return new List<Client>
{
new Client { Id= 1, Name = "Antonov", AffiliationDate = DateTime.Today.AddDays(random.Next(500) * -1) },
new Client { Id= 2, Name = "Bhor", AffiliationDate = DateTime.Today.AddDays(random.Next(360) * -1) },
new Client { Id= 3, Name = "Cicerón", AffiliationDate = DateTime.Today.AddDays(random.Next(480) * -1) },
new Client { Id= 4, Name = "Demeter", AffiliationDate = DateTime.Today.AddDays(random.Next(700) * -1) },
new Client { Id= 5, Name = "Hola Mundo", AffiliationDate = DateTime.Today.AddDays(random.Next(120) * -1) },
new Client { Id= 6, Name = "Mundo Nuevo", AffiliationDate = DateTime.Today.AddDays(random.Next(900) * -1) },
};
}
}
}

AutoCompleteBox

Finalmente tenemos que hacer lo siguiente en el XAML y en el .cs de la ventana que usara el AutoCompleteBox. La propiedad ValueMemberPath nos permite definir que propiedad de nuestra clase queremos que use para filtrar y el enumerado FilterMode nos ofrece una gran variedad de modos de filtrado.

<Window x:Class="AutoCompleteBoxWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
Title="[WPF] Toolkit's AutocompleteBox" Height="300" Width="300">
<Grid>
<!-- Si es que es suficiente haciendo override al metodo .ToString() de la clase en cuestión -->
<!--<toolkit:AutoCompleteBox x:Name="AutoCompleteBox"
ValueMemberPath="Name"
FilterMode="Contains"
VerticalAlignment="Top"
Margin="24"/>-->

<toolkit:AutoCompleteBox x:Name="AutoCompleteBox"
ValueMemberPath="Name"
FilterMode="Contains"
VerticalAlignment="Top"
Margin="24">
<toolkit:AutoCompleteBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Foreground="Orange"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding AffiliationDate, StringFormat='ddd dd MMM yyyy'}"/>
</StackPanel>
</DataTemplate>
</toolkit:AutoCompleteBox.ItemTemplate>
</toolkit:AutoCompleteBox>
</Grid>
</Window>
using AutoCompleteBoxWPF.Services;
using System.Windows;

namespace AutoCompleteBoxWPF
{
public partial class MainWindow : Window
{
private readonly ApplicationService _applicationService = new ApplicationService();

public MainWindow()
{
Loaded += MainWindow_Loaded;

InitializeComponent();
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.AutoCompleteBox.ItemsSource = this._applicationService.ReadAll();
}
}
}

CodePlex

Código fuente disponible en: WPF -> AutoCompleteBoxWPF

[WPF] ¿Como generar un Código QR y exportarlo en PNG?

En la presente publicación ejemplificaré como lograr estos objetivos ayudándonos de una librería llamada QrCode.Net la cual esta disponible para WinForms (no lo he probado) y WPF. Para este post he usado la versión 0.3 porque la 0.4 es Pre-release.

Con esta librería hay un par de formas de hacer esto: usando el control QrCodeControl o la clase QrEncoder.

QrCodeControl

Lo único que hay que hacer acá es dibujarlo correctamente en el XAML e ir actualizando su propiedad Text.

<Window x:Class="GenerateQR.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:qr="clr-namespace:Gma.QrCodeNet.Encoding.Windows.WPF;assembly=Gma.QrCodeNet.Encoding"
Title="[C#] ¿Cómo generar un Código QR y exportarlo en PNG?" Height="350" Width="525">
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtCode" Margin="6" TextChanged="txtCode_TextChanged"/>
<Button x:Name="btnExport" Grid.Column="2" Content="Exportar PNG" Margin="6" Click="btnExport_Click"/>
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<qr:QrCodeImgControl Grid.Column="0" Margin="6" x:Name="qrControl" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="Auto" Width="Auto" />
<Image Grid.Column="1" x:Name="imgQR" />
</Grid>
</Grid>
</Window>
        private void txtCode_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
if (string.IsNullOrWhiteSpace(txtCode.Text)) return;

//QrCodeImgControl
qrControl.Text = txtCode.Text;
}

QrEncoder

Para usar esta clase primero tenemos agregar las referencias a System.Drawing, PresentationCore y WindowsBase. Una vez agregadas las referencias continuamos:

        private Bitmap GetQRBitmap(string content)
{
var qrEncoder = new QrEncoder();
var code = qrEncoder.Encode(content);
var bitmapImage = new Bitmap(code.Matrix.Width, code.Matrix.Height);

for (int j = 0; j < code.Matrix.Height; j++)
for (int i = 0; i < code.Matrix.Width; i++)
bitmapImage.SetPixel(i, j, code.Matrix[i, j] ? System.Drawing.Color.Black : System.Drawing.Color.White);

return bitmapImage;
}

private BitmapImage BitmapToImageSource(Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();

return bitmapimage;
}
}

private void txtCode_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
if (string.IsNullOrWhiteSpace(txtCode.Text)) return;

//Image
var imageSource = BitmapToImageSource(GetQRBitmap(txtCode.Text));
this.imgQR.Width = imageSource.PixelWidth;
this.imgQR.Height = imageSource.PixelHeight;
this.imgQR.Source = imageSource;
this.imgQR.UpdateLayout();
}

Exportando el PNG

Aquí nos valemos de la clase PngBitmapEncoder y en este ejemplo estoy exportando el archivo en la misma carpeta del ejecutable para ser simples.

        private void btnExport_Click(object sender, RoutedEventArgs e)
{
string path = Guid.NewGuid().ToString() + ".png";

using (FileStream fileStream = new FileStream(path, FileMode.Create))
{
PngBitmapEncoder pngBitmapEncoder = new PngBitmapEncoder();
pngBitmapEncoder.Frames.Add(BitmapFrame.Create((WriteableBitmap)qrControl.Source));
pngBitmapEncoder.Save(fileStream);
fileStream.Close();
}
}

CodePlex

Código fuente disponible en: CSharp -> GenerateQR

[Windows App Development] Modal personalizado para Windows Phone


Sé que en Windows Phone no existen Windows ni Modals y que probablemente van en contra de los lineamientos generales de experiencia de usuario del Sistema Operativo, pero como nada me impide hacerlo y ya que no es muy complicado enseñaré como hacer uno propio.

C#

Empezamos creando una clase que extienda de ContentControl (porque es un control que tendrá un contenido, sino seria suficiente con Control como el BusyIndicator) con la siguiente definición:

XAML

Y continuamos definiendo la plantilla del control que acabamos de crear mediante un estilo implícito de la siguiente manera:

Uso

Agregar el namespace del Modal a la página o al control correspondiente:
Y manejar algunos eventos, aunque también se podría hacer usando DataBinding.

CodePlex

Código fuente disponible en: Windows Phone -> CustomModal

[Windows App Development] BusyIndicator personalizado para Windows Phone

Para algunos (incluyéndome) el ProgressBar no es suficiente si lo que queremos es evitar (de alguna forma elegante) que el usuario siga interactuando con la aplicación mientras se esta ejecutando algun proceso. Por eso en este post enseñare como crear un BusyIndicator.

C#

Empezamos creando una clase que extienda de Control con la siguiente definición:

XAML

Y terminamos definiendo la plantilla del control que acabamos de crear mediante un estilo implícito de la siguiente manera:

¿Cómo usar?

Agregar el namespace del BusyIndicator a la página o al control correspondiente y listo:

CodePlex

Código fuente disponible en: Windows Phone -> CustomBusyIndicator