Lilypie Primer PicLilypie Primer Ticker
Mostrando las entradas con la etiqueta .NET Framework. Mostrar todas las entradas
Mostrando las entradas con la etiqueta .NET Framework. Mostrar todas las entradas

martes, 18 de marzo de 2008

Incluir los métodos privados en las pruebas unitarias

Aunque existe un gran debate acerca de si se debe incluir o no los métodos privados en las pruebas unitarias, siempre es bueno disponer de alguna forma de hacerlo.

En este post les mostraré una sencilla forma de invocar métodos privados usando Reflection.

Implementaremos la clase PrivateMethodCaller asi:

public class PrivateMethodCaller
{
public static object Invoke(Type t, string methodName, object[] parameters)
{
MethodInfo mi = t.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic);
return InvokeMethod(mi, null, parameters);
}

public static object Invoke(object instance, string methodName, object[] parameters)
{
MethodInfo mi = instance.GetType().GetMethod(methodName, BindingFlags.NonPublic|BindingFlags.Instance);
return InvokeMethod(mi, instance, parameters);
}

private static object InvokeMethod(MethodInfo mi, object instance, object[] parameters)
{
if (mi == null)
{
throw new InvalidOperationException("No se pudo encontrar el método");
}
return mi.Invoke(instance, parameters);
}
}

Nuestra clase contiene un solo método: Invoke que toma dos formas:

La primera acepta un parámetro tipo Type. Esta versión del método nos permite invocar métodos estáticos.

La segunda acepta un parámetro tipo object. Esta versión nos permite invocar métodos no estáticos.

Veamos ahora como usamos esta clase desde nuestras pruebas unitarias.

Crearemos una clase muy simple que nos servirá como ejemplo:

public class ClassUnderTest
{
private static int StaticMethod(int a, int b)
{
return a + b;
}
private int InstanceMethod(int a, int b)
{
return a + b;
}
}

Hemos definido dos métodos en nuestra clase de prueba. Uno estático y el otro de instancia.

Ahora veamos como implementamos nuestras pruebas unitarias usando NUnit:

[TestFixture]
public class PrivateMethodTests
{
[Test]
public void StaticMethodTest()
{
int res = (int)PrivateMethodCaller.Invoke(typeof(ClassUnderTest), "StaticMethod", new object[] { 1, 2 });
Assert.AreEqual(3, res);
}

[Test]
public void InstanceMethodTest()
{
int res = (int)PrivateMethodCaller.Invoke(new ClassUnderTest(), "InstanceMethod", new object[] { 4,5});
Assert.AreEqual(9, res);
}
}


Como podemos ver ya somos capaces de invocar los métodos privados y testear sus resultados.

Espero que esta información les sea de utilidad.

Saludos.


 


lunes, 25 de febrero de 2008

NHibernate.Timestamp != SQLServer.Timestamp

Al intentar utilizar el control de concurrencia, mediante las etiquetas <timestamp> o <version> de NHibernate junto con el tipo Timestamp de SQL Server, nos encontramos con un mensaje como este:

"Could not cast the value in field ts_times4_ to the Type TimestampType. Please check to make sure that the mapping is correct and that your DataProvider supports this Data Type."

debido a que el tipo Timestamp de SQL Server es recibido como un byte[] en el .NET Framework y no es compatible con los tipos que NHibernate usa para el control de las versiones. (Aunque la documentación de NHibernate diga lo contrario)

Luego de algunas horas intentando resolver este problema encontré un artículo en CodeProject q resuelve el problema.

http://www.codeproject.com/KB/dotnet/OptLocking_PrefixTable.aspx

Ojala les sea de utilidad

jueves, 21 de febrero de 2008

Herramientas para GMail en MSDN CodeGallery

Se publicó en MSDN CodeGallery una libreria de clases muy sencillas, pero q nos pueden ahorrar algún tiempo, que nos permiten integrar nuestras aplicaciones .NET con el excelente servicio de GMail.

Pueden descargar el código desde aqui

Saludos

martes, 19 de febrero de 2008

NHibernate: Intellisense para archivos de configuracion

Un tip para lograr soporte de Intellisense para los archivos de configuración y mapeo (mapping files) de NHibernate

Simplemente debemos copiar los archivos [NhibernateInstallDir]\src\NHibernate\*.xsd en:

[VSInstallDir]\Xml\Schemas -- si estamos usando VS2005, o

[VSInstallDir]\Common7\Packages\schemas\xml -- si aun estamos usando VS2003

Espero les sea de utilidad a la hora de escribir sus archivos xml a mano :)

viernes, 18 de enero de 2008

El codigo fuente del .NET Framework ya está disponible

Cumpliendo con su anuncio de octubre pasado, MS acaba de liberar el código fuente del .NET Framework como material de Referencia y Depuración.

Pueden encontrar el anuncio original aqui,

También se ha posteado una explicacion en profundidad de como configurar VS2008 para depurar el código aqui

Y finalmente una traducción a nuestro idioma aqui


Espero q esta información les sea de utilidad... y un FELIZ Y EXITOSO 2008 a todos <:D

martes, 20 de noviembre de 2007

Recursos adicionales que acompañan a VS2008

Junto con el lanzamiento de VS 2008 se liberaron muchos recursos adicionales que nos ayudarán a dar los primeros pasos en esta nueva plataforma.

Tenemos por ejemplo: Windows Vista P2P Toolkit, Free Game Developer Toolkit, Coding4Fun Developer Toolkit, Controles gratuitos, Host gratuito...y muchos otros.

Pueden encontrar una recopilación interesante en este post.

Espero les sea de utilidad, saludos

lunes, 19 de noviembre de 2007

Ya llegaron VS2008 y .NET Framework 3.5

Hoy fueron liberadas oficialmente las versiones RTM de estos dos productos. Aún no vienen en las tradicionales cajitas que podemos comprar en una tienda, pero podemos descargarlas desde varios sitios:

Si son suscriptores de MSDN pueden descargar el producto sin costo desde el sitio de msdn.

Si no son suscriptores:

* se puede bajar versiones de prueba de 90 dias de VS Team Suite aqui.
* Una versión de prueba de 90 días de Team Foundation System está disponible aqui.
* Una versión de prueba de 90 días de VS Professional estará disponible en los próximos dias.
* Las ediciones Express (gratuitas) están disponibles aqui.

y finalmente, si solamente quieren descargar el .NET framework 3.5, pueden encontrarlo aqui.

Espero les sirvan esos links, en los próximos les haré un resumen de las principales innovaciones que trae esta nueva versión.

El Training kit de Visual Studio 2008 y .NET Framework 3.5 ya está disponible

A partir de hoy está disponible el Training Kit de VS 2008 y .NET Framework 3.5. Es un archivo comprimido de poco más de 120 Mb que contiene presentaciones en PowerPoint, Demos y Labs.

Se puede descargar de aqui

Saludos

martes, 13 de noviembre de 2007

C# 3.0: Variables locales implícitamente tipadas

Una innovación interesante de la versión 3 de C# es la posibilidad de que el programador quede liberado de definir el tipo de dato de cada variable dejando a criterio del compilador el inferir el tipo de la variable, en base al valor a que se inicialice la variable.

Asi por ejemplo si inicializamos una variable x con el valor 1 (uno), resulta obvio que x es una variable de tipo int. O si inicializamos y con el valor "Hola mundo", es posible afirmar que y es del tipo string. Entonces es posible que el compilador determine (infiera) el tipo de la variable que estamos declarando, liberándonos de esta tarea.

C# 3 incluye la palabra reservada var que le indica al compilador que debe inferir el tipo de la variable que estamos declarando. Por ejemplo, a partir de la instrucción:

var x = 1;
var y
= "Hola mundo";

el compilador puede inferir que x es de tipo int. y que la variable y es del tipo string.

Es un error pensar que var declare una variable tipo Variant, es decir, una variable que puede cambiar su tipo dinámicamente. var simplemente nos evita tener que especificar el tipo de una variable al momento de declararla. Para el CLR cada variable tiene un y solo un tipo de dato, por tanto, el siguiente código no compila:

var x = 1;
x
= "Hola"; // Esta linea no compila

porque el compilador determinó que x es del tipo int, por lo que es ilegal asignarle un valor del tipo string.

El valor de inicialización es obligatorio cuando se declara una variable con var, asi el siguiente código no compila:

var x; // Esta linea no compila

porque el compilador necesita un valor a partir del cual pueda inferir el tipo de dato.


También es posible inferir el tipo de los arrays usando var, asi:

var numeros = new[] {1,2,3};

a partir de new[], el compilador sabe que estamos declarando un Array, y a partir de la lista de valores puede determinar el tipo de sus elementos.

Finalmente var también puede ser usada para declarar tipos complejos como listas o diccionarios, asi:

var lista = new List<int>();
var diccionario
= new Dictionary<int, string>();

lunes, 12 de noviembre de 2007

.NET Framework 3: Expresiones de inicialización de Objetos

Otra sencilla pero muy útil innovación del .NET Framework 3.0 son las expresiones de inicialización de objetos.

Si, por ejempo, tenemos la clase Persona con las propiedades Código, Nombre, FechaDeNacimiento y Estado, y queremos inicializar sus propiedades al momento de instanciarla, estábamos obigados a crear un constructor como este:

public Persona(int codigo, string nombre,
DateTime fechaDeNacimiento,
int estado)
{
this.Codigo = codigo;
this.Nombre = nombre;
this.FechaDeNacimiento = fechaDeNacimiento;
this.Estado = estado;
}

Entonces teniamos la posibilidad de invocar al constructor asi:


Persona p = new Persona(10, "Juan Perez",
new
DateTime(1980, 12, 10), 1);


con lo que la instancia es creada y sus propiedades inicializadas.

Ahora, con la versión 3 del .NET Framework tenemos la posibilidad de usar una forma alternativa que nos evita tener que implementar un constructor como el anterior. Esta nueva funcionalidad se implementa mediante las Expresiones de Inicialización de Objetos, que toman la siguiente forma:


Persona p = new Persona { Codigo=10,
Nombre
="Juan Perez", Estado=1 };


Es importante notar que nuestra clase debe implementar un constructor sin parámetros.

viernes, 9 de noviembre de 2007

Innovaciones del .NET Framework 3: Propiedades implementadas automáticamente

Otra innovación del .NET Framework 3 es la posibilidad de implementar automáticamente las propiedades, reduciendo la cantidad de código que debemos escribir.

En muchos casos implementamos propiedades triviales asi:

private string telefono;

public string Telefono
{
get { return telefono; }
set { telefono = value; }
}

En este caso get y set tienen implementaciones triviales, ya que get simplemente devuelve el valor de telefono y set asigna el valor recibido en value al campo telefono. Antes estábamos obligados a 1) declarar un campo privado telefono, 2) implementar get y set a mano.

Ahora, el .NET Framework 3 nos ahorra todo ese trabajo, ya que podemos reemplazar todo el código anterior por:

public string Telefono { get; set;}

Ya no tenemos la necesidad de declarar un campo privado ni de implementar get y set.

También tenemos la posibilidad de utilizar modificadores como private para get y set, asi:

public string Telefono { get; private set;}

Asi logramos tener una propiedad de solo lectura.

Esta sencilla innovación nos evita mucho del trabajo repetitivo, y nos permite concentrarnos en la implementación de aquellas propiedades que sí requieren procedimientos más complejos. Una característica muy bienvenida.


jueves, 8 de noviembre de 2007

.NET Framework 3: Extension Methods

Una innovación interesante de la versión 3.0 del .NET Framework son los denominados Extension Methods.

Para entender el concepto, tomemos la clase System.String. Esta clase tiene una gran cantidad de métodos que nos permiten realizar muchas operaciones sobre las cadenas. Sin embargo, en ocasiones he necesitado invertir una cadena, y después de escarbar por un buen rato, tuve que aceptar resignado que esta clase no implementa un método que permita realizar esta operación.

Analicemos un par de alternativas para solucionar este problema.

1. Crear una clase derivada de String e implementar un método Reverse() en ella. Esta opción no es viable en este caso concreto porque la clase String está sellada (sealed) por lo que no admite clases derivadas.

2. Implementar una biblioteca que incluya un método ReverseString y pasarle la cadena como parámetro, asi:

public class MyLib
{
public static string ReverseString(string s)
{
// el código aqui.
}
}

Entonces invocaríamos al método de esta manera:

string rev = MyLib.ReverseString("Cadena a invertir"');

Esta alternativa cumple con el propósito, pero es algo incómoda de usar, sería mucho más conveniente contar con el método Reverse() implementado directamente en la clase String.

Aqui es donde los Extension Methods hacen su aparición, ya que permiten añadir funcionalidades a un tipo existente del CLR sin necesidad de crear una clase derivada ni de recompilar el tipo original. Entonces un Extension Method nos permitiría hacer una llamada como esta:

string rev = miCadena.Reverse();

o incluso:
string rev = "Cadena a invertir".Reverse();
Veamos entonces como se implementa un Extension Method:

public static class MisExtensiones
{
public static string Reverse(this string s)
{
string buffer = "";
foreach (char c in s.ToCharArray())
{
buffer
= c.ToString() + buffer;
}
return buffer;
}
}

Este código nos permite hacer algunas precisiones respecto a la forma de implementar los Extension Methods:

  • Deben ser definidos dentro de una clase estática.
  • Deben ser declarados estáticos.
  • Toman como parámetro el tipo que se quiere extender precedido de la palabra reservada this.

Nada más, cumpliendo esos pocos requisitos podemos extender cualquier clase del .NET Framework.

Veamos un ejemplo interesante, tomado del este post del blog de ScottGu:


public static bool In(this object o, IEnumerable c)
{
foreach (object i in c)
{
if (i.Equals(o))
{
return true;
}
}
return false;
}

Este método extiende la clase Object y nos permite saber si un objeto está contenido dentro de una colección. Invocamos el método asi:

bool isInArray = miObjeto.In(miColeccion);

Lo más interesante es que al extender una clase, la nueva funcionalidad también estará disponible en todas sus clases derivadas. Entonces al aplicar esta técnica en las clases base adecuadas, podremos extender el .NET Framework de forma limpia, ordenada y transparente.

miércoles, 7 de noviembre de 2007

Linq: Nunca es tarde para aprender

Sin duda, debería haberme subido al tren de Linq hace muchísimo tiempo pero mas vale tarde que nunca. Hoy me propongo iniciar mi aprendizaje de Linq, y estaré posteando a diario mis avances, con la esperanza de que lo que escriba aquí le sea útil a alguien que, aunque tarde como yo, quiere iniciarse en esta tecnología.

Estoy usando el libro "Linq for Visual C# 2005" de Fabio Claudio Ferracchiati, un libro de poco más de 170 páginas, que nos servirá por lo menos para dominar los rudimentos, para luego pasar a cosas más avanzadas.

Primero lo primero: Necesitamos datos que podamos consultar.


Linq puede consultar datos de diversas fuentes como objetos en memoria (Linq to Objects), bases de datos SQL, Ficheros XML entre otros. Empezaré usando Linq To Objects hasta dominar la sintaxis y luego (pronto, espero) pasaré a experimentar con las otras fuentes de datos.


Empecemos definiendo una sencilla clase Persona:


public class Persona
{
private
int id;

private
int idRol;

private
string apellido;

private
string nombre;

public string Apellido
{
get { return apellido; }
set { apellido = value; }
}

public string Nombre
{

get { return nombre; }

set { nombre = value; }

}

public
int IdRol
{

get { return idRol; }

set { idRol = value; }

}

public int Id
{
get { return id; }
set { id = value; }
}

public Persona(int id, int idRol, string apellido, string nombre)
{
this.Id = id;
this.IdRol = idRol;
this.Apellido = apellido;
this.Nombre = nombre;
}

}

Posteriormente extenderemos esta clase y añadiremos otras, pero por el momento nos sirve tal cual está.

Para que nuestros objetos puedan ser consultados mediante Linq, deben implementar la interface IEnumerable, por lo que podemos crear una lista de Personas y aprovechamos para poblarla con algunos elementos:

personas= new List<Persona>();
personas.Add(new Persona(1, 1, "Anderson", "Brad"));
personas.Add(new Persona(2, 2, "Gray", "Tom"));
personas.Add(new Persona(3, 2, "Perez", "Juan"));
personas.Add(new Persona(3, 3, "Morales", "Pedro"));


Ya estamos listos para empezar a consultar los datos usando Linq. Una consulta realmente simple es:

var query = from p
in personas
select
p;

Hay mucho que explicar en esta simple consulta.

  1. var: El .NET Framework incluye un nuevo tipo de datos denominado var, que significa Variant. Es una variable local implícitamente tipada, o sea que adopta un tipo determinado de acuerdo al contexto.
  2. from p in personas select p: Si manejamos SQL notaremos la similitud inmediatamente, pues en SQL escribiríamos SELECT * FROM Personas. En Linq primeramente especificamos a (o las) fuentes de las que extraeremos nuestros datos, en este caso "personas" que es una lista. En algún lugar leí que se decidió poner el datasource (la claúsula from) en primer lugar (a diferencia de SQL) con el fin de dar soporte a cosas tales como IntelliSense, imagino que también existen otras razones. La variable "p" representa un objeto dentro de la colección "personas".
  3. Select p: Esta claúsula equivale a SELECT * de SQL, es decir: "Recuperar todos los campos".

Asi de fácil, con esas 3 lineas, obtenemos todos los elementos de la colección personas y asignamos el resultado a la variable query.

Podemos ver los resultados de nuestra consulta asignando la variable query que hemos obtenido a un bindingSource, asi:

bindingSource1.DataSource = query;

entonces podremos visualizar inmediatamente los resultados en un DataGridView, por ejemplo. No olvidar fijar la propiedad AutoGenerateColumns a true.

Un par de consultas más, a manera de ejemplo:

var query = from p
in personas

select new { p.Apellido, p.Nombre};

Esta consulta nos permite seleccionar únicamente los campos que nos interesan, en este caso, el apellido y el nombre.

Por último,

var query = from p
in
personas
where p.Id == 1
select new { p.Apellido, p.Nombre };

Como se puede suponer, la cláusula where nos permite seleccionar únicamente aquellos elementos que cumplen una determinada condición. Podemos utilizar cualquier combinación de expresiones booleanas que el .NET framework nos permita, eso nos permitirá construir consultas muy complejas.

Hasta aquí llegamos con esta breve introducción.

martes, 6 de noviembre de 2007

Visual Studio 2008 se lanza a finales de noviembre

Pues si... En el evento de Microsoft TechEd Developers 2007 en Barcelona se anunció que Visual Studio 2008 y la versión 3.5 del .NET Framework estarán disponibles a finales de este mes. Algunos meses antes de la fecha inicialmente fijada que era febrero 2008.

Asi que ya no falta mucho para tener entre nosotros la version final de esta herramienta. Es de esperar de MS prepare alguna promoción como la que se hizo en el programa Desarrollador cinco estrellas cuando VS 2005 fue lanzado, lo que nos permitió a muchos desarrolladores contar con el programa en forma totalmente gratuita. Habrá que estar atentos a ver que noticias nos tienen.

Saludos.

jueves, 4 de octubre de 2007

Código fuente del .NET Framework estará disponible en VS2008

Scott Guthrie nos anuncia que la versión final de VS 2008 incluirá la opción de descargar el código fuente de las librerias del .NET Framework con documentación y soporte de depuración incluídas.

Esto será de gran ayuda para lograr un mejor conocimiento de la estructura y el funcionamiento interno del framework, logrando que nuestras aplicaciones lo aprovechen de la mejor manera.

Pueden encontrar el post de ScottGu aqui

viernes, 21 de septiembre de 2007

Se lanza xUnit.net

Ayer fue anunciado el lanzamiento de un nuevo framework de pruebas unitarias para la plataforma .NET: xUnit.NET.

A decir de sus creadores (los mismos de NUnit), esta nueva herramienta implementa lecciones aprendidas en varios años de uso de NUnit.

Entre las principales diferencias entre NUnit y xUNIT.NET se citan:

  • Instanciación de objetos para cada Test Method.
  • Se eliminan los atributos [SetUp] y [TearDown]
  • Se elimina el atributo [ExpectedException] , y se lo reemplaza por Assert.Throws()
  • Funcionalidad Tipo Aspect
  • Varios atributos han sido eliminados:[TestFixture], [Ignore], [SetUp], [TearDown], [ExpectedException], [TestFixtureSetup], [TestFixtureTearDown].
  • Uso de genéricos en los Asserts.
  • Uso de delegados anónimos.
Se incluye una versión de consola y también se integra con Visual Studio 2005 mediante TestDriven.NET.

La página del proyecto es http://www.codeplex.com/xunit

El blog en que uno de los autores anuncia el lanzamiento del producto se encuentra en http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html

Aprovecharé estos dias para probar este framework y les comentaré los resultados.

martes, 17 de julio de 2007

Ejecutar un instalador .msi que requiere .Net Framework 1.1 bajo .Net Framework 2.0

Si tenemos un archivo de Windows Installer (archivo .msi) que requiere el .Net Framework 1.1 pero en nuestro equipo solo tenemos instalado el .Net Framework 2.0, la aplicación se rehúsa a instalarse y simplemente obtenemos un mensaje como este:

“This setup requires the .NET Framework versión 1.1.4322. Please install the .NET Framework and blah blah blah…”

Una solución sería descargar e instalar el .Net Framework 1.1 como lo exige nuestra aplicación, con la consiguiente pérdida de tiempo y espacio en nuestro disco. Afortunadamente existe otra solución más directa: Modificar el archivo .msi

Ocurre que los archivos de instalación tienen instrucciones para verificar que se cumplan ciertas condiciones antes de ejecutarse, entonces la solución es quitar esas instrucciones con un editor.

Existe una herramienta de Microsoft llamada Orca que sirve para editar los archivos de instalación (.msi, .msm, .psp, y .msp). Esta herramienta está incluida en el Windows SDK, que puede ser descargado libremente. Se puede encontrar más información sobre la herramienta, así como el sitio de descarga aqui.

Una vez instalada la herramienta, abrimos el archivo .msi que queremos editar y buscamos la tabla Custom Action en el panel de la izquierda.


Entonces ubicamos las acciones DIRCA_CheckFx y VSDCA_VsdLaunchConditions y las eliminamos.

Nada más, guardamos el archivo y ya debería funcionar sin mayores protestas.

Ojalá les sea útil.

lunes, 16 de julio de 2007

Un ComboBox que muestra los Fonts instalados en el equipo

En este post compartiré con ustedes una sencilla forma de implementar un ComboBox (o un ListBox) que muestra los tipos de letra que tenemos instalados en el equipo, asi:

Vamos directo al código. Primero necesitamos crear en nuestro Form un campo privado que almacenará los tipos de letra instalados en el equipo y servirá como DataSource de nuestro ComboBox.

private InstalledFontCollection installedFonts = new InstalledFontCollection();

A continuación debemos configurar las Propiedades DataSource y DisplayMember del ComboBox, haremos esto en el constructor del Form, asi:

private void Form1_Load(object sender, EventArgs e)
{
comboBox1.DataSource = installedFonts.Families;
comboBox1.DisplayMember =
"Name";
comboBox1.DrawMode =
DrawMode.OwnerDrawFixed;
}

También hemos fijado la Propiedad DrawMode a OwnerDrawFixed, algo que también podríamos haber hecho usando el diseñador gráfico.

Finalmente la verdadera acción tiene lugar en el evento DrawItem del Combo, que implementamos así:

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
FontFamily family = installedFonts.Families[e.Index];
FontStyle style = FontStyle.Regular;
if (!family.IsStyleAvailable(style))
style = FontStyle.Bold;
if (!family.IsStyleAvailable(style))
style = FontStyle.Italic;
Font fnt = new Font(family, 10, style);
Brush brush;
if (e.State == DrawItemState.Selected)
{
brush = new SolidBrush(Color.White);
}
else
{
brush = new SolidBrush(comboBox1.ForeColor);
}


e.DrawBackground();

e.Graphics.DrawString(family.GetName(0),
fnt, brush, e.Bounds.Location);

}

Quizás las líneas en que vamos modificando la variable style merezcan una explicación. Ocurre que no todos los Fonts soportan todos los estilos, así que si no nos aseguramos de que el Font que vamos a utilizar soporte un determinado estilo terminaremos obteniendo una linda Excepción.

Eso es todo, ya tenemos un ComboBox que muestra como lucen nuestras fuentes, haciendo que nuestras aplicaciones sean un poquito más amigables.

martes, 3 de julio de 2007

Arrastrar y mover un Control

Update 2008-09-16.
Pueden descargar el código de este post aqui


En este post expondré una sencilla forma de mover un control dentro su contenedor; algo que no es muy complicado en realidad, pero que tampoco es lo más intuitivo del mundo.

Para lograrlo haremos uso de los eventos MouseDown, MouseUp y MouseDown, implementados en la clase Control, por lo que el código aquí expuesto nos servirá para mover cualquier objeto derivado de dicha clase.

Para empezar creamos un formulario y añadimos un control cualquiera. Para este ejemplo utilizaré un simple Label.

Ahora necesitamos declarar un campo privado del tipo booleano que nos indique si actualmente estamos arrastrando el control.

private bool isDragging = false;

Entonces nos valemos de los eventos MouseDown y MouseUp de nuestro Label para fijar el valor del campo isDragging, asi:

private void label1_MouseDown(object sender, MouseEventArgs e)

{
isDragging = true;

}

private void label1_MouseUp(object sender, MouseEventArgs e)
{

isDragging = false;
}

Ahora si, la verdadera acción ocurre en el evento MouseMove de nuestro Label:

private void label1_MouseMove(object sender, MouseEventArgs e)
{

Control ctrl = sender as Control;
if (isDragging)

{

Point p1 = ctrl.PointToScreen(e.Location);

Point p2 = ctrl.Parent.PointToClient(p1);

ctrl.Location = p2;

}

}

Lo único novedoso de este código es el uso de los métodos PointToScreen y PointToClient que transforman las coordenadas a coordenadas de Pantalla y a coordenadas de Control respectivamente.

Nada más, con estas pocas líneas ya podemos permitir a nuestros usuarios acomodar los controles a su conveniencia, algo muy útil para diseñar formularios, reportes, interfaces de usuario y otras cosas por el estilo.

miércoles, 20 de junio de 2007

La Clase OperatingSystem

En uno de los foros en que participo, un colega preguntaba cómo se puede obtener la versión del Sistema Operativo que estamos ejecutando.

Se puede obtener una referencia a la versión del SO que estamos ejecutando con el siguiente código:

OperatingSystem os = Environment.OSVersion;

Entonces, a través de las propiedades de la clase OperatingSystem podemos acceder a la siguiente información:

os.Platform: La plataforma. Ej. Win32, Win32NT,....

os.VersionString: Una cadena con la información completa de nuestro SO
Ej: "Microsoft Windows NT 5.2.3790 Service Pack 2"

os.Version: La versión del SO. Las propiedades que tiene son:
Major, MajorRevision, Minor, MinorRevision y Revision

os.Version.ToString() nos devuelve una cadena de tipo "5.2.3790"

os.ServicePack: Una cadena que muestra la versión del Service Pack instalado.
Ej: "Service Pack 2"

Seguramente esta información le será útil a más de uno, saludos