lunes, 28 de diciembre de 2009

How to use an HTML color from C#

This way...

System.Drawing.Color color = System.Drawing.ColorTranslator.FromHtml("#FFCC66");

That's it!

lunes, 3 de agosto de 2009

Cómo crear setups para Windows Mobile

Esto es algo en lo que poca gente piensa cuando esta haciendo un proyecto, sin embargo siempre se tiene que crear y aunque no es trivial tampoco es tan transparente, aqui la receta para hacer un setup.


Prerequisitos: Tener una aplicación para Windows Mobile, ya sea para SmartPhone o Handheld, obvio me refiero al código.


Crear un assembly de nombre CustomInstaller.dll con la siguiente clase:

-------------------------------------------------------------------------------------


using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using Microsoft.Win32;
[System.ComponentModel.RunInstaller(true)]
public class SetupApp : System.Configuration.Install.Installer
{
private const string INI_FILE = @"\Setup.ini";
public SetupApp()
{
AfterInstall += new System.Configuration.Install.InstallEventHandler(SetupApp_AfterInstall);
AfterUninstall += new System.Configuration.Install.InstallEventHandler(SetupApp_AfterUninstall);
}
void SetupApp_AfterInstall(object sender, System.Configuration.Install.InstallEventArgs e)
{
//---to be executed when the application is installed---
string ceAppPath = GetWindowsCeApplicationManager();
if ( ceAppPath.Equals(string.Empty) )
return;
string iniPath = GetIniPath();
Process.Start(ceAppPath, iniPath);
}
void SetupApp_AfterUninstall(object sender, System.Configuration.Install.InstallEventArgs e)
{
//---to be executed when the application is uninstalled---
string ceAppPath = GetWindowsCeApplicationManager();
if ( ceAppPath.Equals(string.Empty))
return;
string iniPath = GetIniPath();
MessageBox.Show(iniPath);
Process.Start(ceAppPath, string.Empty);
}
public static string GetWindowsCeApplicationManager()
{
//---check if the Windows CE Application Manager is installed---
string ceAppPath = KeyExists();
if ( ceAppPath.Equals(string.Empty))
{
MessageBox.Show("Windows CE App Manager not installed", "Setup", MessageBoxButtons.OK, MessageBoxIcon.Error);
return string.Empty;
}
return ceAppPath;
}
public static string GetIniPath()
{
//---get the path of the .ini file---
string ini = "\"" + Path.Combine(Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location), "Setup.ini") + "\"";
return ini;
}
public static string KeyExists()
{
//---get the path to the Windows CE App Manager from the registry---
RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\CEAPPMGR.EXE");
if (key == null )
return string.Empty;
else
return key.GetValue(string.Empty, string.Empty).ToString();
}
}

-------------------------------------------------------------------------------------



Paso 1: Crear un proyecto de setup Smart Device Cab Project, agregarle el output del proyecto de la aplicación Mobile.

Paso 2: Crear un nuevo proyecto con Visual Studio -> Setup Project, es decir, como si fuéramos a generar un proyecto de instalación común y corriente.

Paso 3: Agregar el cab resultante del paso 1 al proyecto de Setup del paso 2

Paso 4: Agregar un archivo .ini con el siguiente contenido, éste archivo llevará por nombre Setup.ini


[ceAppManager]
Version = 1.0
Component = HomsMobile
[HomsMobile]
Description = HomsMobile Application
Uninstall = HomsMobile
CabFiles = HomsMobileSetup.cab



Nota: Reemplazar HomsMobile por el nombre del proyecto de la aplicación Windows Mobile que vayamos a generar.


Paso 5: Una vez creado el setup.ini, lo agregamos también al proyecto de setup del paso 2

Paso 6: Creamos un Custom Action en el proyecto de setup del paso 2 y lo agregamos en el folder "Install" y agregarmos el assembly de CustomInstaller.dll



Paso 7: Finalizamos


Observaciones:

Una vez que se ha compilado el assembly de CustomInstaller se puede ocupar para proyectos subsecuentes..

El archivo ini no debe llevar retorno de carro en la última línea, si se la dejan ya no funciona.

miércoles, 22 de abril de 2009

Desarrollo en BlackBerry

En estos últimos días he estado adentrnadome en este ambiente de desarrollo que al parecer se ha puesto de moda en los ejecutivos y los no tanto, pues bien, la verdad es que no había visto una de cerca, en lo personal me parecía una copia de PalmOS pero con una mejor interface de usuario, solo eso, la calidad de pantalla, gráficos y aplicaciones me parecía muy similar. En fin, fué hasta que tuve la necesidad de hacer una aplicación que tuve la oportunidad de comparar y esta es mi comparativa con otros ambientes de tecnología móvil.

1. iPhone
2. Windows Mobile
3. Palm
4. Black Berry (y esta en cuarto porque no hay mas, sino estaría igual al último)

Su ambiente de desarrollo es pobre, hablo del JDE, la programación en java lo hace supuestamente universal pero en realidad lo unico que lo hace es mas lento contra otras aplicaciones en lenguaje nativo.

La ayuda es prácticamente inexistente, es dificil encontrar un ejemplo de algo, la interface del editor no es intuitiva, es lenta y en ocasiones se atasca en memoria.

El simulador es bastante malo, de hecho se tronó mandandome un error de la Virtual Machine de Java, tuve que reinstalarlo cuando no tenía ni 10 horas de haberlo instalado. El WiFi virtual es pésimo, no se conecta y no hay manera de configurarlo, mucho menos un sitio de help para hacerlo.

Se requieren al menos 3 o 4 veces mas líneas de código que en otros ambientes para hacer lo mismo y con menor calidad.

La calidad del diseño de pantallas que se puede hacer resulta muy pobre a menos que se programe todo en modo gráfico, lo cual encarecería bastante los desarrollos.

Y lo peor, es que para desarrollar aplicaciones empresariales se tiene que comprar un servidor de BES (blackberry enterprise service) que además cuesta una lana adicional, te obligan a comprar y comprar, que decepcionante.

Finalmente, recomiento ampliamente el iPhone para plataforma de aplicaciones empresariales y como segunda opción Windows Mobile, ya que palm OS fué descontinuado el año pasado, aún con esto es una mejor plataforma que BlackBerry

miércoles, 28 de enero de 2009

How to get the id associated with a description in a ComboBox

Todo mundo te dice que si usas el DataSource cargas los items de una lista, pero y si no tengo una lista y tengo que generar mi control usando XAML para que se pinte de manera dinámica??? ah pues la solución es la siguiente

<ComboBox Name="prueba">
<ComboBoxItem Uid="A">Prueba1</ComboBoxItem>
<ComboBoxItem Uid="B">Prueba2</ComboBoxItem>
<ComboBoxItem Uid="C">Prueba3</ComboBoxItem>
<ComboBoxItem Uid="D">Prueba4</ComboBoxItem>
</ComboBox>

Finalmente cuando quieras obtener el uid asociado a un item seleccionado

string id = prueba.SelectedItem.Uid

Aunque para colocarlo de manera inmediata no he encontrado cómo a menos que sea barriendo todos los items del combo para luego hacer la asignación hacia el elemento SelectedItem.

viernes, 23 de enero de 2009

How to format a number with a prefix

Ah, esto es muy trivial, tanto que siempre que lo necesito usar se me olvida, asi que para evitarme estarlo buscando igual aqui lo pongo:

Problema:
Supongamos que requerimos formatear el siguiente número 300, para que quede así $300.00

Solución:
string number = string.Format("$ {0:#.00}", 300);

Adicional:
Que tal que ahora necesitamos rellenar espacios a la izquierda con ceros para completar 4 posiciones, ah pues fácil:

string number = sring.Format("{0:0000}", 300); lo que nos da como resultado -> 0300

Linq and dynamic queries

Pues asi tal cual, no se llevan... Linq hace un mapeo hacía estructuras que regresa un query y/o stored procedure por lo que es prácticamente imposible que si estas haciendo una migración de un sistema de hace unos 3 o 4 años lo puedas migrar sin muchas broncas. En mi caso yo me encontré de mandar llamar a un stored procedure de n posibles los cuales me regresan igual número de columnas: 2, pero el resultado a veces me regresaba los nombres de las columnas con diferente descripción, no podía agregar los stored procedures al dbml, o mas bien si podía, pero son n, asi que era poco funcional, después de mucho buscarle de plano me dí por vencido, no se puede, así que mi solución fué colgarme de la conexión de linq y usé obtemos del tipo Db que se encuentran en System.Data.Common y sólo de esta manera logré poder acceder al resultado de una llamada de un stored procedure de manera dinámica.

Definitivamente Linq en mi opinión solo funciona si la base de datos se genera pensando con la mentalidad de tablas a estructuras, de otra manera no será eficiente y sí te dará muchos dolores de cabeza

viernes, 16 de enero de 2009

WebBrowser Control WPF

Estuve probando este control con la versión 2008 del VS y SP1 y, aparentemente todo esta OK, pero si en un momento dado quieres hacer algo mas elaborado como capturar eventos o más simple: obtener la referencia hacia un control, pues nomás no sirve si de mera casualidad tienes un javascript ya no puedes tener acceso al body del HTML, le estuve buscando de mil maneras y nomas no se puede asi que de plano lo dejé por la paz e intenté con un control que venía con el VS2003, éste es: AxInterop.SHDocVw

Con este no tuve problemas en acceder a los recursos del HTML, aún cuando este contenga scripts, en el siguiente post colocaré el código de ejemplo con el cual ontengo referencias a los controles de una página web.

jueves, 15 de enero de 2009

Add an event to a button created in runtime WPF

En el post pasado coloqué el procedimiento para generar controles en tiempo de ejecución a través de XAML, bueno eso estuvo bien, pero ¿ahora de que me sirve tener un botón creado dinámicamente si no le puedo asociar un evento? lo más sencillo sería en este caso asociar el evento directamente en el XAML del botón de la siguiente manera

<Button Name="Test" Click="Test_Click" ></Button>

Sin embargo al ejecutar este código en adición al anterior post referente a la creación de controles de manera dinámica lo único que obtendremos es un error en tiempo de ejecución que indica que se debe compilar previamente el XAML, lo cual bueno, nos da otra tarea que no queremos hacer.

Problema:

¿Cómo asociar un evento a un botón que fué creado en runtime?

Solución.

Del post anterior hacemos los siguientes cambios:

StringReader reader = new StringReader(xaml);
XmlReader xml = XmlReader.Create(reader);

Grid rootElement = (Grid)XamlReader.Load(xml);
Button cmd = (Button)rootElement.FindName("bnNextWindow");

//Si el botón existe agregamos el evento
if (cmd != null)
cmd.Click += new RoutedEventHandler(bnNextWindow_Click);

rootElement.Children.Add(rootElement);

Obviamente debemos generar el método que se suscribirá al evento:

void bnNextWindow_Click(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}

Y listo!

miércoles, 14 de enero de 2009

Create controls in WPF at runtime

El WPF ha sido mi dolor de cabeza desde hace un par de días, así que me he pasado un buen rato consultando otros sitios, como en muchas otras ocasiones me he quedado con la intención de una vez resuelto mi problema poder exponer mi caso y la solución, asi que, en esta ocasión aqui va.

Problema: ¿Cómo le hago para generar controles de WPF en tiempo de ejecución? bueno pues la manera en cómo yo lo necesitaba era a través de XAML, es decir, tengo una clase que se encargada de generar el XAML y que se encuentra fuera de la ventana principal, es decir, no tiene referencias hacia System.Windows.blahblahblah, de esta manera una vez que se genera el XAML guardo esto en un string común y corriente y se lo paso a la ventana para que lo agregue a su grid principal.

Los controles a generar son:

TextBox
Button
Label

Generar el XAML es lo más sencillo, ésto es:

<grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x="http://schemas.microsoft.com/winfx/2006/xaml">

<textbox width="68.4" name="UC_0" margin="115.2,14.4,0,0" verticalalignment="Top" horizontalalignment="Left" height="23"></textbox>

<label width="105.6" name="Lbl_0" margin="27.6,16,0,0" verticalalignment="Top" horizontalalignment="Left" height="23">Operador: </label>

<button name="bnNextWindow" width="75" margin="12,0,0,12" verticalalignment="Bottom" horizontalalignment="Left" height="23">Siguiente</button>

</grid>

Solución:

Ahora viene lo bueno, ¿cómo hago para que éste XAML se muestre en la ventana?

string xaml = "<Grid xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">";

xaml += "<TextBox Width="68.4" Name="UC_0" Margin="115.2,14.4,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Height="23"></TextBox>";

xaml += "<Label Width="105.6" Name="Lbl_0" Margin="27.6,16,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Height="23">Operador: </Label>";

xaml += "<Button Name="bnNextWindow" Width="75" Margin="12,0,0,12" VerticalAlignment="Bottom" HorizontalAlignment="Left" Height="23">Siguiente</Button>";

xaml += "</Grid>";

StringReader reader = new StringReader(xaml);
XmlReader xml = XmlReader.Create(reader);
this.Content = XamlReader.Load(xml);

Finalmente al correr el programa nos queda esto:



Referencias:

System.Windows.Markup
System.IO
System.Xml