Que el .NET te acompañe

Resistance is futile, you will be assimilated
SecondNug: Guille Community Tour

Hola a tod@s,

Después de las vacaciones empezamos el año en SecondNug con un eventazo de la mano de Guillermo Som "el Guille".
En esta ocasión concluye con nosotros su gira "Guille Community Tour" donde expondrá las novedades del VB9:

- Tipos anulables
- Métodos parciales
- Ensamblados amigos
- Varianza y contravarianza
- Operador ternario
- Agilidad del runtime
- Relajación de delegados
- Y por supuesto LINQ con:
       - Tipos anónimos
       - Expresiones Lambda
       - Expresiones de consulta al estilo SQL
       - Inferencia de tipos
       - Inicializadores de objetos
       - Inicializadores de arrays y colecciones
       - Métodos extensores

Para los que no pudisteis asistir de forma presencial ahora tenéis la oportunidad de hacerlo online, será el próximo martes 20 de enero. 

Para poder asistir al evento necesitas Microsoft Office Live Meeting, si todavía no lo tienes descárgalo gratuitamente en el siguiente enlace.

Puedes registrarte en el evento gratuitamente en el siguiente enlace.

Posted: 13/1/2009 12:24 por Carmen Sanchez | con 10 comment(s) |
Archivado en:
Desplegando Crystal Reports 2008 con Clickonce

Hola a tod@s,

Hace tiempo publiqué un artículo donde comentaba que para obtener los paquetes de redistribución de Crystal Reports 2008 había que bajárselos de internet (Componentes para instalación de una aplicacion con Crystal Reports 2008), ahora os voy a comentar como usar el paquete redistribuible con clickonce.

Imaginad que queremos hacer el despliegue de una aplicación por clickonce y que usa crystal reports 2008 y que no se permite que se descarguen los prerrequisitos desde la ubicación del proveedor, por eso nos queda el hacerlo desde un recurso compartido o desde la ubicación de la propia aplicación

Pero al publicar nos encontramos con el siguiente error:

"La ubicación de instalación de los requisitos previos no se estableció como 'sitio Web del proveedor de componentes' y el archivo 'CrystalReports 12.0\CRRuntime_12_0_mlb.msi' del elemento 'Crystal Reports 2008' no se encuentra en el disco"

Para arreglar esto y hacer que nuestra aplicación se publique correctamente basta descargarse dicho archivo desde http://www.businessobjects.com/ y luego pegarlo en C:\Archivos de programa\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\CrystalReports 12.0 en caso de tener VS2005.

Espero que les haya servido de ayuda.

Saludos.

Posted: 10/11/2008 10:28 por Carmen Sanchez | con 5 comment(s) |
Archivado en:
SecondNug - ASP.NET Ajax y Jquery
Hola a tod@s,
 
Os recuerdo que mañana 4 de noviembre los chicos de SecondNug nos van a explicar como usar ASP.NET Ajax y Jquery, por lo que si eres un desarrollador Web y todavía no lo has usado te animo que veas esta charla y saques tus propias conclusiones. Yo ahora desarrollo en WinForms pero os aseguro que si lo hiciera en Web usaría Ajax, el refresco asíncrono de datos es muy bueno para que no se haga tanto postback y el usuario no tenga esa sensación de tardanza, y además tiene otras muchas ventajas que con mucho gusto se explicarán en el evento. Aquí os dejo los detalles y recordad que aunque no podáis verla en directo, estos eventos se graban y se pueden descargar para poder verlas otro día.

 
Introducción a ASP.NET AJAX y JQuery (Noviembre 2008)

El próximo martes 4 de Noviembre en Secong Nug abordamos uno de los temas que más han dado de hablar en el mundo del desarrollo web; AJAX.

La aparición de AJAX permitió al desarrollador cambiar la forma de afrontar sus desarrollos en la web tradicional y poder crear páginas en ASP.NET 2.0, actualizando partes de la página sin una recarga completa de la misma, dotando a nuestras aplicaciones web una experiencia de usuario rica equiparable a las tradicionales aplicaciones Windows.

Esta revolucionaria funcionalidad se ve reforzada con el nuevo framework de javascript JQuery, que nos proporciona una tremenda productividad y gran sencillez de uso, con la que podemos dotar de complejas interfaces de usuarios a nuestra aplicación web de una forma más fácil.

Si quieres dar tus primeros pasos con AJAX y JQuery no te pierdas el evento que nos ofrecerá Marc "Marckys" Rubiño durante dos horas repletas de ejemplos prácticos y accesibles.

    El evento será entre las 19:30 y las 21:30 (GMT+2), y como en anteriores ocasiones, se retransmitirá vía Web a través de Live Meeting

    Si no tenéis Live Meeting podéis descargarlo aquí.

    No olvidéis registraros al evento en el siguiente enlace.

    Posted: 3/11/2008 21:55 por Carmen Sanchez | con 3 comment(s) |
    Archivado en:
    A por la estrella de platino

    ¡Qué bonito es el color del platino!, ¿verdad?, pues si, ya podemos ser desarrolladores de platino, no lo dejes pasar.

    Para la estrella de platino tendremos que pasar un examen de LINQ y otro de Silverlight 2.0, siempre y cuando previamente tengas la estrella de oro, mola ;-)

    Para quien todavía no conozca el programa desarrollador 5 estrellas, simplemente decir que es una iniciativa de Microsoft para aprender sobre diferentes aspectos del framework 2, 3 y 3.5 bajandote documentación, código  y probar suerte con exámenes para ver si has aprendido algo. No es difícil, desde mi punto de vista cualquiera se lo puede ir sacando, ademas si suspendes lo puedes volver a intentar transcurridad 24 horas y lo más importante es que siempre aprendes algo o repasas temas.

    http://www.dce2005.com

    Saludos

    Posted: 7/10/2008 11:41 por Carmen Sanchez | con 1 comment(s)
    Archivado en:
    Cuidado con tener varias versiones de Crystal Reports instaladas

    Hola a tod@s,

    Yo soy de la opinión que se debería estar a la última, pero en la realidad no siempre es factible, ¿quien no tiene algún proyecto en alguna tecnología un tanto desfasada y sin tiempo para migrar?, e incluso a veces la solución no es migrar. Pues yo tengo el caso de tener varias versiones de Crystal por tener proyectos ya sea en framework 1.1 y 2.0, por eso tengo instaladas en mi máquina el CR XI y el CR 2008.

    Primero comentar que el CR 2008 es compatible tanto con el VS 2003, VS 2005 y VS 2008.

    El problema que he tenido al respecto es que cuando me bajo del sourcesafe un proyecto del framework 1.1 que no tenía previamente en mi pc y que los informes están con la versión XI, cuando abro la solución el VS automáticamente me toma las referencias a la versión 2008 del crystal. Es fácil detectar esto, cuando tenemos un proyecto con informes de crystal en una versión previa a la 2008, cuando se abren el visual estudio nos tiene que avisar de ello y dar la posibilidad de seguir con esa versión o cambiar a la nueva.

    Si no nos ha salido el mensaje de aviso, malo, se pueden haber cambiado las referencias y estas apuntar a la versión del 2008 y darnos errores de compilación. Para solucionar esto basta con irnos a las propiedades del proyecto y mirar en las rutas de acceso a referencias, podremos comprobar que hay una ruta que apunta a "C:\Archivos de programa\Business Objects\Common\4.0\managed\dotnet" (esto para framework 1.1, para el framework 2.0 la ruta es ...\managed\dotnet2), tendríamos que quitarla y agregar la siguiente:

    Nota: Aunque el proyecto esté bajo un sourcesafe, las rutas de acceso a referencia se pueden cambiar sin afectar al control de código.

     Yo en estos casos, si se puede, lo mejor es migrar a la última versión y tener una sola, pero vuelvo a repetir que a veces es imposible por la magnitud del proyecto o porque el entorno no lo soporta o porque no hay tiempo ni dinero. De todas formas, es compatible tener varias versiones de Crystal instaladas, pero ya sabéis que os podéis encontrar esto.

     Saludos.

    Evento en SecondNug, Software Factories con VSTS: ¿verdadero o falso?

    Hola a tod@s,

     Os recuerdo que mañana tendrá lugar el evento "Software Factories con VSTS, ¿verdadero o falso?" a manos de "El Bruno" para SecondNug. Como siempre via Live Meeting, así que no hay excusas vivas donde vivas, y si mañana no puedes asistir, 24 h. mas tarde lo podrás escuchar en diferido, pero habrá un sorteo de regalos en directo, ¿quieres ser el ganador de alguno?.

     Estos son los detalles del evento.

    Mucho se ha escrito sobre Software Factories, sobre conceptos para la industrialización del proceso de desarrollo y sobre otros temas que sirven para marear a la gente. Es por eso que el siguiente paso, que es llevar esta teoría a un escenario real, es mucho más complejo de lo que parece.

    Visual Studio Team System, es una herramienta que gracias a un modelo muy flexible permite solucionar numerosos problemas que plantea la teoría; sin embargo hasta la llegada de "Rosario" todavía queda mucho por explorar.

    En esta sesión veremos parte de las capacidades de extensión VSTS, y algunos ejemplos sobre como traer a la realidad los conceptos básicos para la creación de activos para las Software Factories.

    Nivel: 300 ó + (Vamos a darle caña a Visual Studio)

    El evento será entra las 19:30 y las  21:30 (GMT+2), y como en anteriores ocasiones, se retransmitirá vía Web a través de Live Meeting.

    Si no tienes Live Meeting, puedes descargarlo en el siguiente enlace

    Podéis registraros en el evento en el siguiente enlace

    Saludos.

    Posted: 16/6/2008 8:57 por Carmen Sanchez | con 12 comment(s) |
    Archivado en:
    Evento Visual Studio Team System 2008 en SecondNug

    Hola a tod@s,

     Os recuerdo que mañana tendrá lugar el evento de SecondNug "Novedades Visual Studio Team System 2008" cuyo ponente es el gran Luis Fraile donde nos expondrá principalmente:

    - Herramientas de Profiling
    - Integración Continua
    - Mejoras en la gestión del código fuente
    - Modos de trabajo Online y Offline

    Como siempre será retransmitido por Live Meeting y os podéis registrar aquí.

    Espero veros!!!

    Un saludo

    Posted: 2/6/2008 13:11 por Carmen Sanchez | con 1 comment(s) |
    Archivado en:
    Infragistics - UltraSpellChecker

    Hola a tod@s,

    Después de un tiempecito sin escribir nada reanudo mi actividad, ya se sabe, Madrid en Mayo con esos puentes maravillosos y un catarro o alergia de 3 semanas me han hecho no tocar el ordenador salvo lo estrictamente necesario en el trabajo ;-).

    Uno de los controles mas fascinantes de Infragistics a mi parecer es el corrector ortográfico. 

    Para el ejemplo voy a usar la base de datos AdventureWorks para SQL Server 2005 Express, y la versión de Infragistics 7.3 para CLR2 con VS2005.  

    Voy a crear una aplicación Windows en C#. Para habilitar la correción ortográfica es tan sencillo como arrastrar de la barra de tareas el control  UltraSpellChecker y lo llamo ultraSpellChecker1. Ahora modificamos las siguientes propiedades:

    • Dictionary, le indico la ruta del diccionario que voy a usar para corregir. Infragistics, cuando lo instalas, te proporciona unos diccionarios. Para el caso que nos concierne "C:\Archivos de programa\Infragistics\NetAdvantage for .NET 2007 Vol. 3 CLR 2.0\Dictionaries\es-spanish-v2-whole.dict"
    • Mode, le indico "DialogOnValidatingAndAsYouType" esto quiere decir que validará el campo una vez que pierda el foco.
    • ShowDialogsModal, le indico "True".
    • UserDictionary, en esta propiedad le indicaremos la ruta donde se encuentra el diccionario donde iremos agregando las palabras que no reconoce pero que nosotros las damos como buenas.

    Estas son las propiedades que creo son mas relevantes. Pero os invito a que veáis el resto.

    Nota: en caso de que no tengáis los controles de Infragistics en la barra de herramientas del Visual Studio ver el artículo “Crear barra de herramientas”

    Ahora voy a añadir dos controles de texto en un formulario, un textbox (control de Microsoft) y un ultratexteditor (control de Infragistics), y para que se active el corrector en ambos solo hay que, para el textbox nos aparecerá una nueva propiedad que es "SpellCheckerSettings en UltraSpellChecker1" y le daremos el valor "Enabled = True", y para el ultratexteditor le indicaremos a la propiedad "SpellChecker" el ultraSpellChecker asociado, en nuestro caso "ultraSpellChecker1".

    Simplemente con esto que hemos hecho, cada vez que introduzcamos un dato en una de las cajas de texto y nos salgamos, automáticamente nos saldrá una ventana para corregir los datos introducidos.

    El problema es que por defecto esta ventana está en inglés. Si queremos cambiarlo a español tendremos que hacer algo parecido a esto:

    private void Form1_Load(object sender, EventArgs e) {

        // Traduzco los mensajes al espa¤ol en la ventana de correcci¢n ortogr fica
        Infragistics.Shared.ResourceCustomizer rc = new Infragistics.Shared.ResourceCustomizer();

        rc = Infragistics.Win.UltraWinSpellChecker.Resources.Customizer;
        rc.SetCustomizedString(
    "LS_SpellCheckForm", "Ortograf¡a"); 
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btChange", "&Cambiar");
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btChangeAll", "Cam&biar Todas"); 
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btClose_1", "Cancelar");
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btClose_2", "Cerrar"); 
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btIgnoreAll", "Omitir toda&s");
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btIgnoreOnce_1", "Om&itir una vez"); 
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btIgnoreOnce_2", "&Reanudar");
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btAddToDictionary", "Ag&regar"); 
        rc.SetCustomizedString(
    "LS_SpellCheckForm_btUndo", "&Deshacer");
        rc.SetCustomizedString(
    "LS_SpellCheckForm_lbErrorsFound", "Se han encontrado errores"); 
        rc.SetCustomizedString(
    "LS_SpellCheckForm_lbChangeTo", "Cambiar a:");
        rc.SetCustomizedString(
    "LS_SpellCheckForm_lbSuggestions", "Sugerencias:");
    }

    Y si ahora corremos el ejemplo, ya se nos muestra en español ;-).

    Nota: Recomiendo que a la hora de usar este tipo de cambio de idioma, el valor de la etiqueta en cada idioma se haga en ficheros de recursos, ya sea a nivel de formulario o de proyecto que es donde lo haría en este caso.

    Espero que os haya sido útil.

    Un saludo.

    Posted: 26/5/2008 15:13 por Carmen Sanchez | con 7 comment(s)
    Archivado en:
    Infragistics - Crear barra de herramientas

    Hola a tod@s,

    Como mi intención es escribir varios artículos sobre controles de Infragistics, éste va a ser uno que voy a usar de referencia para pasos previos.

    Cuando terminamos de instalarnos los controles de Infragistics por defecto éstos no nos aparecen en la barra de herramientas del Visual Studio, podemos hacerlo a la antigua usanza, creandonos una nueva ficha e ir agregando los controles a mano. Pero Infragistics en su instalación nos proporciona un script para la línea de comandos que nos lo hace muy bien, porque nos crea una ficha donde incluso nos indica la versión que estamos usando y nos agrega todos los controles. Para ejecutar el script ver la siguiente imagen

    Y cuando volvamos a abrir nuestro Visual Studio nos encontraremos con lo siguiente:

    Listo para usarse ;-).

     Un saludo.

    Posted: 19/5/2008 14:22 por Carmen Sanchez | con no comments
    Archivado en:
    Solo queda un día!!!

    Hola a tod@s,

    Os recuerdo que mañana tendrá lugar el evento de Mayo de SecondNug  "C# vs VB.NET" con dos pesos pesados, Marino Posadas defendiendo C# y el Guille con VB.NET.

    Espero veros a todos.

    Toda la información la podéis encontrar pinchando aquí

    Un saludo.

    Posted: 5/5/2008 13:38 por Carmen Sanchez | con 1 comment(s)
    Archivado en:
    Ya tengo la estrella de oro!!!

    Hola chic@s,

    Pues sí, hace un rato acabo de aprobar el último exámen que me quedaba. He aprobado todos a la primera excepto el de ADO Entity Framework que lo he aprobado a la segunda, pero si hace unos días os comentaba que el exámen de SQL Server 2008 solo tenía 14 preguntas, el resto ha resultado tener 20 preguntas como siempre, pero cuando suspendí el de Entity siendo la puntuación negativa, la aplicación me felicitaba como si hubiera aprobado. Lo importante es que ya me he quitado este peso de encima y ahora a esperar a que salga la de platino.

     Un saludo.

    Posted: 24/4/2008 21:02 por Carmen Sanchez | con 31 comment(s) |
    Archivado en:
    A por la estrella de oro

    Hola a tod@s,

    Aunque hace ya un tiempecito, el programa "Desarrollador 5 Estrellas 2005" anunciaba que ya estaba disponible la estrella de oro, yo lo dejé aparcado porque la 5º estrella me llevó su tiempo y ultimamente estoy apurada, pero hoy he vuelto con mas fuerzas que nunca y mi primera elección ha sido prepararme el exámen de "Desarrollo para SQL Server 2008" y puedo decir muy satisfecha que lo he aprobado, pero que por poco me da un síncope ya que mientras que estaba haciendo el exámen indicaba que había 20 preguntas para contestar (igual que el resto de exámenes) pero cuando he llegado a la pregunta 14 me ha salido el botón de finalizar, lo que me ha hecho pensar que puntuaba como si fueran 20 preguntas y te termina el exámen con 14 lo que te obliga a contestar todo correctamente, pero no, esta vez parece que puntua sobre 14. Mañana seguiré por el de Entity Framework, a ver si me resulta tan fácil como el de SQL.

    Para el que no lo sepa, la estrella de oro consiste en aprobar 4 exámenes, ADO.NET Entity Framework, Desarrollo para SQL Server 2008, dispositivos moviles con Windows Mobile 6.0 y Desarrollo con Sharepoint 2007.

    Un saludo.

    Posted: 21/4/2008 22:30 por Carmen Sanchez | con 2 comment(s)
    Archivado en:
    Infragistics - Ultragrid (Parte II)

    Hola a tod@s,

    Siguiendo con la serie de Infragistics - Ultragrid, hoy os voy a mostrar un ejemplo de como podemos crear dos columnas de tipo dropdownlist en un grid y que los datos de la segunda columna dependa del elegido en la primera en una aplicación de escritorio.

    Para el ejemplo voy a usar la base de datos AdventureWorks para SQL Server 2005 Express, y la versión de Infragistics 7.3 para CLR2 con VS2005.

    Creamos una aplicación Windows Forms en C#. Arrastramos desde la toolbox un objeto UltraGrid.

    En el evento Load del form rellenamos dos Infragistics.Win.ValueList, el primero de ellos con datos de la tabla Product, cuyo valor será ProductID y el texto será Name, para el segundo lo rellenamos con los datos de ProductInventory, cuyo valor será LocationID y el texto será una composición de los campos Shelf, Bin y Quantity (para saber lo que significa cada campo ver el diccionario de datos de AdventureWorks). Luego nos creamos un datatable con dos columnas ProductID y LocationID y la rellenamos tal y como se vé en el código. Este datatable será el proveedor de datos del Ultragrid. Luego asociamos los valuelist a cada columna.

      private void Form1_Load(object sender, EventArgs e)
            {
                SqlConnectionStringBuilder strCon = new SqlConnectionStringBuilder();
                strCon.IntegratedSecurity = true;
                strCon.DataSource = "CSANCHEZG";
                strCon.InitialCatalog = "AdventureWorks";
                Infragistics.Win.ValueList val = new Infragistics.Win.ValueList();
                Infragistics.Win.ValueList val2 = new Infragistics.Win.ValueList();
                DataTable dt = new DataTable();

               
    using (SqlConnection con = new SqlConnection(strCon.ConnectionString))
                {
                    using (SqlCommand cmd = new SqlCommand("SELECT ProductID, Name FROM Production.Product"))
                    {
                        cmd.Connection = con;
                        SqlDataReader dr;
                        con.Open();
                        dr = cmd.ExecuteReader();

                        while (dr.Read())
                        {
                            val.ValueListItems.Add(dr[0], dr[1].ToString());
                        }
                        con.Close();
                    }

                    using (SqlCommand cmd = new SqlCommand("Select LocationID, 'Shelf: ' + Shelf + ', Bin: ' + Cast(Bin as varchar) + ', Quantity: ' + Cast(Quantity as varchar) from Production.ProductInventory"))
                    {
                        cmd.Connection = con;
                        SqlDataReader dr;
                        con.Open();
                        dr = cmd.ExecuteReader();

                        while (dr.Read())
                        {
                            val2.ValueListItems.Add(dr[0], dr[1].ToString());
                        }
                        con.Close();
                    }
                }
                
                dt.Columns.Add("ProductID", typeof(Int32));
                dt.Columns.Add("LocationID", typeof(Int32));

                DataRow drow;
                for (int i = 1; i < 5; i++)
                {
                    drow = dt.NewRow();
                    drow[0] = i;
                    drow[1] = System.DBNull.Value;
                    dt.Rows.Add(drow);
                }
                dt.AcceptChanges();

                ultraGrid1.DataSource = dt;
                ultraGrid1.DataBind();
                ultraGrid1.DisplayLayout.Bands[0].Columns[0].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.DropDownList;
                ultraGrid1.DisplayLayout.Bands[0].Columns[0].ValueList = val;
                ultraGrid1.DisplayLayout.Bands[0].Columns[0].MinWidth = 200;

               
    ultraGrid1.DisplayLayout.Bands[0].Columns[1].Style = Infragistics.Win.UltraWinGrid.ColumnStyle.DropDownList;
                ultraGrid1.DisplayLayout.Bands[0].Columns[1].ValueList = val2;
                ultraGrid1.DisplayLayout.Bands[0].Columns[1].MinWidth = 200;

             }

    Para que cuando pulsemos en el segundo combo que depende del dato elegido en el primer combo, usamos el evento del Ultragrid AfterRowActivate para que el valuelist asociado al segundo combo se rellene dependiendo del valor seleccionado en el primer combo.

             private void ultraGrid1_AfterRowActivate(object sender, EventArgs e)
            {
                Infragistics.Win.ValueList val2 = new Infragistics.Win.ValueList();
                SqlConnectionStringBuilder strCon = new SqlConnectionStringBuilder();
                strCon.IntegratedSecurity = true;
                strCon.DataSource = "CSANCHEZG";
                strCon.InitialCatalog = "AdventureWorks";

                try
                {
                    if ( ! Equals(ultraGrid1.ActiveRow.Cells["LocationID"].Column.ValueList, null))
                    {
                        using (SqlConnection con = new SqlConnection(strCon.ConnectionString))
                        {
                             using (SqlCommand cmd = new SqlCommand("Select LocationID, 'Shelf: ' + Shelf + ', Bin: ' + Cast(Bin as varchar) + ', Quantity: ' + Cast(Quantity as varchar) from Production.ProductInventory " +
                                                                   "WHERE ProductID=" + (int)ultraGrid1.ActiveRow.Cells["ProductID"].Value))
                            {
                                cmd.Connection = con;
                                SqlDataReader dr;
                                con.Open();
                                dr = cmd.ExecuteReader();

                                while (dr.Read())
                                {
                                    val2.ValueListItems.Add(dr[0], dr[1].ToString());
                                }
                                con.Close();
                            }
                        }

                        ultraGrid1.ActiveRow.Cells["LocationID"].Value = System.DBNull.Value;
                        ultraGrid1.ActiveRow.Cells["LocationID"].ValueList = val2;
                    }
                }
                catch (Exception ex)
                {
                }
            }

    Y para que nuestro segundo combo se actualice cuando seleccionamos un nuevo valor en el primer combo podemos usar el evento CellListSelect.

            private void ultraGrid1_CellListSelect(object sender, Infragistics.Win.UltraWinGrid.CellEventArgs e)
            {
                SqlConnectionStringBuilder strCon = new SqlConnectionStringBuilder();
                strCon.IntegratedSecurity = true;
                strCon.DataSource = "CSANCHEZG";
                strCon.InitialCatalog = "AdventureWorks";

                try{
                    if (! Equals(e.Cell.Column.ValueList, null))
                    {
                        if (e.Cell.Column.Key == "ProductID" && e.Cell.Column.ValueList.SelectedItemIndex >= 0 )
                        {
                            Infragistics.Win.ValueList val = new Infragistics.Win.ValueList();
                            Infragistics.Win.ValueListItem item = new Infragistics.Win.ValueListItem();

                           
    item = val.ValueListItems[e.Cell.Column.ValueList.SelectedItemIndex];
       

                           
    using (SqlConnection con = new SqlConnection(strCon.ConnectionString))
                            {
                                 using (SqlCommand cmd = new SqlCommand("Select LocationID, 'Shelf: ' + Shelf + ', Bin: ' + Cast(Bin as varchar) + ', Quantity: ' + Cast(Quantity as varchar) from Production.ProductInventory " +
                                                                       "WHERE ProductID=" + (int)item.DataValue))
                                {
                                    cmd.Connection = con;
                                    SqlDataReader dr;
                                    con.Open();
                                    dr = cmd.ExecuteReader();

                                    while (dr.Read())
                                    {
                                        val.ValueListItems.Add(dr[0], dr[1].ToString());
                                    }

                                    con.Close();
                                 }
                            }

                            ultraGrid1.ActiveRow.Cells["LocationID"].Value = System.DBNull.Value;
                            ultraGrid1.ActiveRow.Cells["LocationID"].ValueList = val;
                         }
                    }
                }
                catch (Exception ex)
                {}

            }

    Espero les resulte útil.

    Un saludo.

    Posted: 17/4/2008 17:32 por Carmen Sanchez | con 11 comment(s)
    Archivado en:
    Nueva funcionalidad Crystal Reports 2008

    Hola a tod@s,

    Estoy haciendo la migración de informes hechos con Crystal Reports XI a 2008 y me he encontrado con un caso en que he tenido que rehacer el informe, lo curioso es que cuando estaba haciendo una agrupación me he fijado en las opciones de los grupos.

     
    Crystal Reports XI
     
    Crystal Reports 2008

    Ahora se puede decir que cada grupo aparezca en una página distinta desde las opciones de los grupos y no como antes que había que hacerlo en los detalles de las secciones.

    Un saludo.

    Ejemplo Validación con Enterprise Library en aplicación Windows (parte II)

     Hola a tod@s,

    Os dejo con la segunda parte del artículo "Ejemplo Validación con Enterprise Library en aplicación Windows", este también está traído de mi antiguo blog.

    Para finalizar con el ejemplo de aplicando validaciones con Enterprise Library, ahora os voy a explicar como implementarlo desde el app.config, de tal forma que si cambian no tengamos que volver a recompilar la solución, simplemente modificando el XML del archivo de configuración nos baste, ¿a que es guapísimo?

    Los pasos que he seguido son:

    1º. Agregar una nuevo proyecto de librerías de clases a la solución que tenía. Lo he llamado Prueba.
    2º. Al proyecto prueba le he añadido una clase que he llamado NewEmployee, y le he definido las mismas propiedades que la clase Employee, pero sin añadirle validaciones.

    1

    3º. He compilado el nuevo proyecto, y lo he referenciado al primero ELValidation.
    4º. Ahora con boton derecho sobre el App.Config pulsamos en "Edit Enterprise Library Configuration"

    2

    5º. Nos aparece el App.Config editado de la siguiente forma.

    3

    6º. Con botón derecho sobre la ruta completa del App.Config podemos agregar nuevos elementos de los application Block. Para el ejemplo que estamos haciendo, un Validation Application Block.

    4

    Cuando aparece desactivado el menú, es porque ya lo tenemos agregado en el App.Config, como podéis observar en el dibujo.

    7º. Ahora con botón derecho sobre "Validation Application Block" agregamos un nuevo Type. Como podréis observar nos salen un montón de tipos excepto el que nos interesa que es nuestro proyecto Prueba. Para eso hay que pulsar en "Load an Assembly", y buscamos nuestro Assembly "Prueba"

    5 
    6

    8º. Ahora podemos elegir "Prueba" como nuestro Type. Os aviso de que cuando se carga un nuevo Assembly, luego el resto de Assemblies que había se expanden y es un poco costoso encontrar el que queremos. Con paciencia vamos contrayendo los assemblies que no nos interesan hasta que llegamos al de nuestro ejemplo, en este caso el Assembly "Prueba" tiene un NameSpace "Prueba" y dentro de él la clase "NewEmployee" que queremos validar.

    7

    9º. Una vez que tenemos en la edición del App.Config la clase que queremos validar con botón derecho sobre ella elegimos nuevo "RuleSet", le podemos cambiar el nombre a lo que queremos. Ahora con botón derecho sobre el conjunto de reglas elegimos nuevo "Choose Members", nos aparece una nueva ventana con todas las propiedades y métodos de la clase, si pinchamos sobre el check de Properties nos selecciona todas.

    8

    10º. Ahora con botón derecho sobre cada propiedad podemos ir añadiendo validadores, o carpetas de validadores "and" o "or" para poner varias condiciones a la vez. Como muestro en las siguientes imágenes, podemos añadir validadores de no nulidad, de longitud de cadena, expresiones regulares, de fechas y customizados.

    9
    En esta imagen he añadido a cada propiedad dos validadores, uno de no nulidad y otro de cadena, fecha, expresion regular o customizado según el caso, excepto para la propiedad LastName que solo he dejado una única validación de cadena. Es lo mismo que tenía en el artículo anterior mediante código para la clase Employee.


    10
    Como vemos en al imagen, el valor de no nulidad es bastante sencillito, le podemos nombrar como queramos, y para mostrar el texto cuando se produce la excepción de validación, lo podemos hacer mediante la propiedad MessageTemplate si no vamos a tener multi idioma, o con un fichero de recursos, en mi caso como quiero multi idioma lo he hecho con el fichero de recursos, simplemente hay que especificar el nombre de la cadena del fichero de recursos de la que extrae el mensaje gracias a la propiedad MessageTemplateResourceName, y donde se encuentra el fichero de recursos gracias a la propiedad MessageTemplateResourceTypeName, en este caso es "ELValidation.Resource1, ElValidation", es decir, "NameSpace.Clase, NameSpace". El Visual Studio también nos permite encontrar el fichero de recursos pulsando en 15 cuando nos posicionamos en la propiedad, sería encontrar el Assembly donde está y seleccionarlo.


    11
    Para los validadores de cadena, simplemente es poner el valor menor y el máximo teniendo en cuenta si queremos que se validen incluso esos valores mediante las propiedades LowerBoundType y UpperBoundType respectivamente. El mensaje a mostrar funciona exactamente en todos los validadores de la misma manera que lo que he explicado en el validador no nulo.


    12
    Lo mismo para las fechas, podemos elegir un valor mínimo y uno máximo, decidir si queremos que sea el año, el mes, el día o la fecha entera la que se validad.


    13
    También podemos validar mediante expresiones regulares, e incluso tener un fichero de recursos con el patrón a seguir.


    14 
    También podemos crearnos nuestros propios validadores. A esto tengo que comentar que he tenido que modificar ligeramente la clase NifValidator para que me funcione con respecto a lo que tengo en el artículo anterior.
    He modificado el primer construtor de la clase NifValidator para que quede:
    public NifValidator(NameValueCollection attributes)
                : base(null, null)
            {
            }

    También he tenido que modificar la clase NifValidatorAttribute cambiando la llamada al constructor de NifValidator en el método DoCreateValidator quedando:
    protected override Validator DoCreateValidator(Type targetType)
            {
                return new NifValidator(null, null);
            }

    11º. Ahora solo nos queda modificar el ValidatorProvider del formulario Form1 para que mire en el App.Config

    16

    También he modificado el evento Load del formulario para crearme un objeto de tipo NewEmployee, que sus propiedades se rellenen con lo que inserto en las cajas de texto y ya estaría.

               NewEmployee otroEmpleado = new NewEmployee(); //Como variable de clase

                //Esta parte estaría en el Load del formulario
                otroEmpleado.Code = txtCode.Text;
                otroEmpleado.Nif = txtNIF.Text;
                otroEmpleado.FirstName = txtFirstName.Text;
                otroEmpleado.LastName = txtLastName.Text;
                otroEmpleado.DateOfBirth = dtpDateOfBirth.Value;
                otroEmpleado.Email = txtEmail.Text;

               //Este código iría en el botón de validar
               if (otroEmpleado != null)
                {
                    vpEmployee.Enabled = true;
                    this.ValidateChildren();
                }

    Al final el formulario tiene que quedar así si no se introduce ningún dato y lo hemos validado

    17

    Sería un buen ejercicio que a apartir de las fuentes que he dejado en el artículo anterior, el que tenga interés en el tema, intente reproducir la situación que he comentado en este artículo.

    Espero que os haya servido.

    Saludos.

    Infragistics - UltraGrid (parte I)

    Hola a tod@s,

    Después de llevar bastantes meses (desde mi antiguo blog) prometiendo escribir sobre los controles de Infragistics voy a comenzar con un pequeño ejemplo de cómo rellenar un UltraGrid por código y darle algo de formato y funcionalidad.

    Para el ejemplo voy a asar la base de datos AdventureWorks para SQL Server 2005 Express, y la versión de Infragistics 7.3 para CLR2 con VS2005.

    Creamos una aplicación Windows Forms en C#. Arrastramos desde la toolbox un objeto UltraGrid

    NOTA: Para tener los objetos de Infragistics en la barra de herramientas lo podemos hacer de forma tradicional (que no es muy idónea en este caso) o ejecutar la herramienta “Create Visual Studio Toolbox Tab” como muestro en la imagen:

    Esto hace que nos aparezca una nueva pestaña en nuestra barra de herramientas con los controles de infragistics.

    Cuando arrastramos un control UltraGrid en un formulario nos aparece un asistente para formatear el grid, pero para este ejemplo pulsamos en el botón finish y ponemos su propiedad Dock a Fill

    Ahora en el evento Load del formulario accedemos a base de datos y rellenamos un DataTable para luego asociarlo al grid. Nos quedará algo como esto:

    private DataTable dtDatos = new DataTable();

    private void Form1_Load(object sender, EventArgs e)       

    {

                SqlConnectionStringBuilder strCon = new SqlConnectionStringBuilder();
                strCon.IntegratedSecurity = true;
                strCon.DataSource = "CSANCHEZG";
                strCon.InitialCatalog = "AdventureWorks";
                using (SqlConnection con = new SqlConnection(strCon.ConnectionString))
                {
                    using (SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Production.Product", con))
                    {
                        da.Fill(dtDatos);
                    }
                }

               
    ultraGrid1.DataSource = dtDatos;
                ultraGrid1.DataBind();

                FormateoGrid();

            }

    Como podemos observar en el código, tenemos la llamada a un método que va a formatear nuestro grid, el código del método será:

    private void FormateoGrid(){
                ultraGrid1.DisplayLayout.Override.AllowRowFiltering = Infragistics.Win.DefaultableBoolean.True;
                ultraGrid1.DisplayLayout.GroupByBox.Prompt = "Arrastra aquí alguna cabecera para agrupar por ella";
                ultraGrid1.DisplayLayout.Override.RowSelectorHeaderStyle = Infragistics.Win.UltraWinGrid.RowSelectorHeaderStyle.ColumnChooserButton;           
                ultraGrid1.DisplayLayout.Override.RowSelectors = Infragistics.Win.DefaultableBoolean.True;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductID"].Hidden=true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductID"].ExcludeFromColumnChooser = Infragistics.Win.UltraWinGrid.ExcludeFromColumnChooser.True;
                ultraGrid1.DisplayLayout.Bands[0].Columns["Name"].Header.Caption = "Nombre";
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductNumber"].Header.Caption = "Número del Producto";
                ultraGrid1.DisplayLayout.Bands[0].Columns["MakeFlag"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["MakeFlag"].ExcludeFromColumnChooser = Infragistics.Win.UltraWinGrid.ExcludeFromColumnChooser.True;
                ultraGrid1.DisplayLayout.Bands[0].Columns["FinishedGoodsFlag"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["FinishedGoodsFlag"].ExcludeFromColumnChooser = Infragistics.Win.UltraWinGrid.ExcludeFromColumnChooser.True;
                ultraGrid1.DisplayLayout.Bands[0].Columns["Color"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["Color"].Header.Caption = "Color";
                ultraGrid1.DisplayLayout.Bands[0].Columns["SafetyStockLevel"].Header.Caption = "Cantidad mínima del inventario";
                ultraGrid1.DisplayLayout.Bands[0].Columns["ReorderPoint"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ReorderPoint"].Header.Caption = "Nivel del inventario";
                ultraGrid1.DisplayLayout.Bands[0].Columns["StandardCost"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["StandardCost"].Header.Caption = "Costo estándar";            ultraGrid1.DisplayLayout.Bands[0].Columns["ListPrice"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ListPrice"].Header.Caption = "Precio de Venta";
                ultraGrid1.DisplayLayout.Bands[0].Columns["Size"].Header.Caption= "Tamaño";
               
    ultraGrid1.DisplayLayout.Bands[0].Columns["SizeUnitMeasureCode"].Header.Caption = "Unidad de Medida del Tamaño";
                ultraGrid1.DisplayLayout.Bands[0].Columns["WeightUnitMeasureCode"].Header.Caption = "Unidad de Medida del Peso";
                ultraGrid1.DisplayLayout.Bands[0].Columns["Weight"].Header.Caption = "Peso";
                ultraGrid1.DisplayLayout.Bands[0].Columns["DaysToManufacture"].Header.Caption = "Dias para crearlo";
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductLine"].Header.Caption = "Linea del Producto";
                ultraGrid1.DisplayLayout.Bands[0].Columns["Class"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["Class"].Header.Caption = "Clase";
                ultraGrid1.DisplayLayout.Bands[0].Columns["Style"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["Style"].Header.Caption = "Estilo";
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductSubcategoryID"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductSubcategoryID"].Header.Caption = "Subcategoria del producto";
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductModelID"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ProductModelID"].Header.Caption = "Modelo";
                ultraGrid1.DisplayLayout.Bands[0].Columns["SellStartDate"].Header.Caption = "Fecha inicio venta";
                ultraGrid1.DisplayLayout.Bands[0].Columns["SellEndDate"].Header.Caption = "Fecha find venta";
                ultraGrid1.DisplayLayout.Bands[0].Columns["DiscontinuedDate"].Header.Caption = "fecha de discontinuidad";
                ultraGrid1.DisplayLayout.Bands[0].Columns["rowguid"].Hidden = true;
                ultraGrid1.DisplayLayout.Bands[0].Columns["rowguid"].ExcludeFromColumnChooser = Infragistics.Win.UltraWinGrid.ExcludeFromColumnChooser.True;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ModifiedDate"].ExcludeFromColumnChooser = Infragistics.Win.UltraWinGrid.ExcludeFromColumnChooser.True;
                ultraGrid1.DisplayLayout.Bands[0].Columns["ModifiedDate"].Hidden = true;
             } 

    La propiedad ultraGrid1.DisplayLayout.Override.AllowRowFiltering hace que nos aparezcan unos botones en la cabecera los cuales nos dan la posibilidad de filtrar.



    Las propiedades ultraGrid1.DisplayLayout.Override.RowSelectorHeaderStyle = Infragistics.Win.UltraWinGrid.RowSelectorHeaderStyle.ColumnChooserButton; y
                ultraGrid1.DisplayLayout.Override.RowSelectors = Infragistics.Win.DefaultableBoolean.True; nos dan la posibilidad de que podamos elegir las columnas que queremos mostrar u ocultar con un botón a la izquierda de la cabecera.

    La propiedad ultraGrid1.DisplayLayout.GroupByBox.Prompt = "Arrastra aquí alguna cabecera para agrupar por ella"; nos permite (tal y como se ve) poner el texto que queramos, por defecto es un texto en inglés.

    Para cada columna he usado las siguientes propiedades:

    Hidden:  hace que el campo no aparezca, pero no quiere decir que no aparezca en el selector de columnas.
    ExcludeFromColumnChooser : esta propiedad hace que no aparezca en el selector de columnas con lo que si el campo es visible, el usuario nunca podrá ocultarlo y si es invisible, el usuario nunca lo podrá ver.
    Header.Caption : es el texto de la cabecera de cada columna.

    Hay muchísimas propiedades que si os interesa podéis ir investigando.

    Y para acabar el ejemplo, quiero que cuando el tamaño sea “XL” el fondo de la fila se muestre en rojo con un degradado. Para ello uso el evento InitializeRow del UltraGrid

    private void ultraGrid1_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e)
            {
                if (e.Row.Cells["Size"].Value.ToString().Trim() == "XL")
                {
                    e.Row.Appearance.BackColor = Color.Red;
                    e.Row.Appearance.BackColor2 = Color.White;
                    e.Row.Appearance.BackGradientStyle = Infragistics.Win.GradientStyle.Vertical;
                }
            }

    Espero que les haya interesado el artículo.

    Saludos.

    Posted: 8/4/2008 14:53 por Carmen Sanchez | con 19 comment(s) |
    Archivado en:
    Ejemplo Validación con Enterprise Library en aplicación Windows

    Este es un artículo que me traigo a geeks de mi antiguo blog.

     
    En el siguiente artículo expongo con un ejemplo muy sencillo como implementar en una aplicación de escritorio validaciones con las Enterprise Library de Microsoft (versión 3.1 Mayo 2007). El ejemplo está hecho en C# y os podéis bajar el código fuente aquí.
     
    Creamos un nuevo proyecto de Windows Application, en mi caso lo he llamado ELValidation. Le añadimos las referencias de Microsoft.Practices.EnterpriseLibrary.Common, Microsoft.Practices.EnterpriseLibrary.Validation y Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WinForms.
     
    En el ejemplo que he creado tengo una clase que representa a un empleado ("Employee.cs"), en la que defino sus propiedades. Es aquí donde mediante atributos en las propiedades le vamos asignando las validaciones.
     
            private string code;
            private string nif;
            private string firstName;
            private string lastName;
            private DateTime dateOfBirth;
            private string email;

            [StringLengthValidator(1, 10, Ruleset = "RuleSet1", MessageTemplateResourceName="InvalidCodeMessage", MessageTemplateResourceType=typeof(Resource1))]
            public virtual string Code
            {
                get { return code; }
                set { code = value; }
            }
            [NifValidator(Ruleset = "RuleSet1", MessageTemplateResourceName="InvalidNifMessage", MessageTemplateResourceType=typeof(Resource1))]
            public virtual string Nif
            {
                get { return nif; }
                set { nif = value; }
            }

            [RelativeDateTimeValidator(-120, DateTimeUnit.Year, -16, DateTimeUnit.Year, Ruleset = "RuleSet1", MessageTemplateResourceName = "InvalidBirthMessage", MessageTemplateResourceType = typeof(Resource1))]
            public DateTime DateOfBirth
            {
                get { return dateOfBirth; }
                set { dateOfBirth = value; }
            }

            [ValidatorComposition(CompositionType.And, Ruleset = "RuleSet1")]
            [RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", MessageTemplateResourceName = "InvalidEmailMessage2", MessageTemplateResourceType = typeof(Resource1), Ruleset = "RuleSet1")]
            [StringLengthValidator(1, 100, Ruleset = "RuleSet1", MessageTemplateResourceName = "InvalidEmailMessage1", MessageTemplateResourceType = typeof(Resource1))]
            public string Email
            {
                get { return email; }
                set { email = value; }
            }

    Como podemos observar en el código, tengo varios tipos de validaciones, para la propiedad Code tengo la validación de que no sea vacía, para el NIF tengo una validación customizada que mas tarde explicaré como hacer, para la edad tengo una validación de fechas y por último, una múltiple validación. Además en este ejemplo he incorporado globalización para que el mensaje de la validación esté en varios idiomas.

    En el atributo StringLengthValidator hay que pasar como parámetros un mínimo, un máximo, el conjunto de reglas que sigue y el mensaje, si no tuvieramos multi-idioma bastaría con poner MessageTemplate = "Lo que sea"

    Para los validadores customizados hay que crearse dos clases, una que herede de Validator<T> y otra que herede de ValidatorAttribute, en mi ejemplo NifValidator.cs y NifValidatorAttribute.cs.

    Éste sería el código de la clase que hereda del validatorAttribute en mi ejemplo:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Practices.EnterpriseLibrary.Validation;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

    namespace ELValidation
    {
        [AttributeUsage(AttributeTargets.All)]
        public class NifValidatorAttribute : ValidatorAttribute

        {
            public NifValidatorAttribute()
            {
            }

            protected override Validator DoCreateValidator(Type targetType)
            {
                return new NifValidator();
            }
        }
    }

    Y el código de la clase donde se hacen las validaciones:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Practices.EnterpriseLibrary.Validation;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Configuration;
    using System.Collections.Specialized;

    namespace ELValidation
    {
        [ConfigurationElementType(typeof(CustomValidatorData))]
        public class NifValidator : Validator<string>
        {

            public NifValidator() : base(null, null)
            {
            }

            public NifValidator(string nif, string messageTemplate)
                : this(nif, messageTemplate, null)
            {
            }

            public NifValidator(string nif, string messageTemplate, string tag)
                : base(messageTemplate, tag)
            {
            }

            protected override void DoValidate(string objectToValidate, object currentTarget, string key, Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResults validationResults)
            {
                if (objectToValidate.Length > 1)
                {
                    if (!ValidateNIF(objectToValidate.ToUpper()))
                    {
                        string message = string.Format(this.MessageTemplate, objectToValidate);
                        this.LogValidationResult(validationResults, message, currentTarget, key);
                    }
                }
                else
                {
                    string message = string.Format(this.MessageTemplate, objectToValidate);
                    this.LogValidationResult(validationResults, message, currentTarget, key);
                }
            }

            protected override string DefaultMessageTemplate
            {
                get { return "El NIF no es válido"; }
            }

            private bool ValidateNIF(string vNif)
            {
                string aux = string.Empty;
                int result;
                aux = vNif.Substring(0, vNif.Length - 1);

                if (aux.Length >= 7 && int.TryParse(aux, out result))
                {
                    aux += letra_nif(Convert.ToUInt32(aux));
                }
                else
                {
                    return false;
                }

                if (vNif == aux)
                {
                    return true;
                }

                return false;

            }

            public string letra_nif(UInt32 dni)
            {
                string s_letra = "TRWAGMYFPDXBNJZSQVHLCKE";
                dni = dni % 23;
                s_letra = s_letra[Convert.ToInt16(dni)].ToString();
                return s_letra;
            }
        }
    }

    Ahora podemos crear un formulario para aplicar la validación:

    1

    Tenemos que agregar un errorProvider y un ValidationProvider, éste último no se encuentra en la barra de herramientas por defecto, yo me he creado una nueva pestaña y lo he agregado

    2

    3

    En las propiedades del ValidationProvider debemos asociarle el errorProvider, decirle que conjunto de reglas debe seguir en la propiedad RuleSetName, en mi caso RuleSet1 y muy importante la propiedad SourceTypeName que será el NameSpace.Clase, NameSpace, en mi caso "ELValidation.Employee, ELValidation".

    Luego en cada textbox nos aparece en sus propiedades una nueva categoria que es Validation donde encontraremos 3 propiedades por cada ValidationProvider que tengamos en el formulario. En mi caso tengo PerformValidation on vpEmployee = true, SourcePropertyName on vpEmployee = Code (nombre de la propiedad de la clase Employee que asocio al textbox y que quiero validar) y por último ValidatedProperty on vpEmployee = Text (aquí ira la propiedad del textbox que queremos validar, en este caso text, si fuera un datetimepicker sería value).

    Y por último, en el evento Load del formulario podemos definir un objeto de tipo empleado, cuyas propiedades se recojan de los textbox del formulario. Y mediante un botón validarlo, de tal manera que la propiedad del ValidationProvider sea true y luego llamar a ValidateChildren del formulario.

    Para que sea multi-idioma el mensaje que muestra el errorprovider basta con crearse los ficheros de recursos oportunos y luego asociarlo a los atributos de las propiedades que queremos validar con MessageTemplateResourceName = "InvalidBirthMessage", MessageTemplateResourceType = typeof(Resource1), en este caso le estaríamos indicando que el mensaje de validación está en el recurso llamado Resource1 y que hace referencia a InvalidBirthMessage.

    Otra cosa importante que he visto, es que cuando tenemos una clase que hereda de otra que tiene validación, las propiedades que no se sobreescriben siguen teniendo la validación del padre, sin embargo las que se sobreescriben la pierden. En el ejemplo que he hecho lo podréis comprobar en la clase Boss que hereda de Employee.

    Espero que os haya ayudado este artículo.

    Saludos.

     
    Componentes para instalación de una aplicacion con Crystal Reports 2008

    Hola a tod@s,

    Al migrar los informes de una aplicación a CR2008 me he encontrado con que al hacer el instalador e intentar añadir los módulos de combinación correspondientes no los tenía lo que no me ocurría en versiones anteriores con lo que investigando me he encontrado con que te los tienes que bajar de la página de business objects.

    Os dejo el enlace:

    http://support.businessobjects.com/downloads/runtime.asp

    Un saludo.

    Posted: 3/4/2008 12:36 por Carmen Sanchez | con 1 comment(s) |
    Archivado en:
    Sandcastle y los Tags XML para los comentarios en código.

    Hola a tod@s,

     El siguiente artículo ya lo publiqué hace bastante tiempo en mi antiguo blog.

    En el siguiente artículo os voy a explicar como agregar comentarios de forma sencilla con Visual Studio 2005 y luego con la herramienta Sandcastle generar una documentación en formato htm o chm. La finalidad es que si nos acostumbramos a que cada vez que hagamos una clase le añadamos comentarios siguiendo las reglas de los tags XML, podamos generar mas tarde una documentación completamente actualizada y de manera bastante rápida de nuestro proyecto. Y en caso de que usemos un generador de código, todavía es mas sencillo hacerlo.

    Si estamos haciendo un proyecto en C# 2005 cuando queremos incorporar un comentario sabemos que se tiene que hacer con "//" pero si añadimos una barra mas nos aparecerá un menú contextual con etiquetas xml que tienen una característica especial:

    /// <summary>
    /// Esta clase hace una importante función. 
    /// </summary>
    public class MiClase{}

    Los distintos tags que hay por ahora son:

    <c> <code> <example> <exception> <include> <list>
    <para> <param> <paramref> <permission> <remarks> <returns>
    <see> <seealso> <summary> <typeparam> <typeparamref> <value>

    Lo que voy a hacer ahora es poneros un ejemplo de como usar estas etiquetas en una clase. He construido una clase con 2 constructores, 5 propiedades y 4 métodos. No he usado todas las etiquetas, pero creo que con este ejemplo os bastará para coger conocimientos sobre el tema y si queréis profundizar siempre podréis seguir la MSDN.

    Para poder llevar a cabo este ejemplo he tenido que instalarme la herramienta Sandcastle y luego usar un programa que facilita la tarea SandcastleGUI, he optado por este programa debido a su sencillez y porque es gratuito, para obtenerlo solo hay que registrarse.

    Para mas información sobre como usar Sandcastle, herramientas que lo usan, etc. visitad este enlace: http://www.sandcastledocs.com/Wiki%20Pages/Home.aspx

    Nota: Otra herramienta que está muy bien es la que podéis encontrar en http://www.codeplex.com/SHFB, lo único que es algo mas compleja que la que yo he usado en este ejemplo y no he encontrado la opción para poder incluir un logo. Lo bueno es que te deja parametrizar mas e incluso tiene una opción para que algunos textos aparezcan en español (pero esta opción no está muy lograda).

    Mi clase con los comentarios añadidos me ha quedado así:

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace comentarios
    {
        /// <summary>
        /// Clase de ejemplo
        /// </summary>
        /// <remarks>
        /// <para>Con esta clase aprenderemos los pasos básicos para <br/>
        /// crear una buena documentación con Sandcastle.</para>
        /// <img src="Class1.png" mce_src="Class1.png"></img>
        ///</remarks>
        public class Class1
        {
            /// <summary>
            /// Constructor principal de la clase.
            /// </summary>
            /// <remarks>
            /// <para>El constructor principal no admite parámetros.</para>
            /// </remarks>
            /// <seealso cref="Class1(String, String, Boolean, Int32, DateTime)"/>
            public Class1()
            {
            }

            /// <summary>
            /// Sobrecarga del Constructor en el que se inicializan las propiedades.
            /// </summary>
            /// <example>
            /// <code>
            /// Class1 miClase = new Class1("uno", "dos", 3, true, DateTime.Today);
            /// string p1 = miClase.Propiedad1;
            /// string p2= miClase.Propiedad2;       
            /// </code>
            /// </example>
            /// <remarks>
            /// Este segundo constructor necesita 5 parámetros, los dos primeros de tipo cadena <br/>
            /// el tercero de tipo booleano, el cuarto de tipo entero y el quinto de tipo fecha.
            /// </remarks>
            /// <param name="prop1">Propiedad 1 de tipo cadena</param>
            /// <param name="prop2">Propiedad 2 de tipo cadena</param>
            /// <param name="prop3">Propiedad 3 de tipo booleano</param>
            /// <param name="prop4">Propiedad 4 de tipo entero</param>
            /// <param name="prop5">Propiedad 5 de tipo fecha</param>
            /// <seealso cref="Class1()"/>
            public Class1(string prop1, string prop2, bool prop3, Int32 prop4, DateTime prop5)
            {
                _sPropiedad1 = prop1;
                _sPropiedad2 = prop2;
                _bPropiedad3 = prop3;
                _iPropiedad4 = prop4;
                _dPropiedad5 = prop5;
            }

            /// <summary>
            /// Campo privado de tipo cadena, propiedad 1.
            /// </summary>
            private string _sPropiedad1 = string.Empty;
            /// <summary>
            /// Campo privado de tipo cadena, propiedad 2.
            /// </summary>
            private string _sPropiedad2 = string.Empty;
            /// <summary>
            /// Campo privado de tipo booleano, propiedad 3.
            /// </summary>
            private bool _bPropiedad3 = false;
            /// <summary>
            /// Campo privado de tipo entero, propiedad 4.
            /// </summary>
            private Int32 _iPropiedad4 = 0;
            /// <summary>
            /// Campo privado de tipo fecha, propiedad 5.
            /// </summary>
            private DateTime _dPropiedad5 = DateTime.MinValue;

            /// <summary>
            /// Propiedad pública que obtiene o establece el valor de <c>_sPropiedad1</c>.
            /// </summary>
            /// <remarks>Propiedad pública que obtiene o establece el valor de <c>_sPropiedad1</c></remarks>
            /// <value>Obtiene o establece el valor del miembro _sPropiedad1.</value>
            /// <seealso cref="_sPropiedad1"/>
            public string Propiedad1
            {
                get {
                    return _sPropiedad1;
                }
                set{
                    _sPropiedad1 = value;
                }
            }

            /// <summary>
            /// Propiedad pública que obtiene o establece el valor de <c>_sPropiedad2</c>.
            /// </summary>
            /// <remarks>Propiedad pública que obtiene o establece el valor de <c>_sPropiedad2</c></remarks>
            /// <value>Obtiene o establece el valor del miembro _sPropiedad2.</value>
            /// <seealso cref="_sPropiedad2"/>
            public string Propiedad2
            {
                get {
                    return _sPropiedad2;
                }
                set {
                    _sPropiedad2 = value;
                }
            }

            /// <summary>
            /// Propiedad pública que obtiene o establece el valor de <c>_bPropiedad3</c>.
            /// </summary>
            /// <remarks>Propiedad pública que obtiene o establece el valor de <c>_bPropiedad3</c></remarks>
            /// <value>Obtiene o establece el valor del miembro _bPropiedad3.</value>
            /// <seealso cref="_bPropiedad3"/>
            public bool Propiedad3
            {
                get {
                    return _bPropiedad3;
                }
                set
                {
                    _bPropiedad3 = value;
                }
            }

            /// <summary>
            /// Propiedad pública que obtiene o establece el valor de <c>_iPropiedad4</c>.
            /// </summary>
            /// <remarks>Propiedad pública que obtiene o establece el valor de <c>_iPropiedad4</c></remarks>
            /// <value>Obtiene o establece el valor del miembro _iPropiedad4.</value>
            /// <seealso cref="_iPropiedad4"/>
            public Int32 Propiedad4
            {
                get { return _iPropiedad4; }
                set { _iPropiedad4 = value; }
            }

            /// <summary>
            /// Propiedad pública que obtiene o establece el valor de <c>_dPropiedad5</c>.
            /// </summary>
            /// <remarks>Propiedad pública que obtiene o establece el valor de <c>_dPropiedad5</c></remarks>
            /// <value>Obtiene o establece el valor del miembro _dPropiedad5.</value>
            /// <seealso cref="_dPropiedad5"/>
            public DateTime Propiedad5
            {
                get { return _dPropiedad5; }
                set { _dPropiedad5 = value; }
            }

            /// <summary>
            /// Método público que devuelve un booleano al comparar la longitud <br/>
            /// de los miembros  _sPropiedad1 y _sPropiedad2
            /// </summary>
            /// <returns>Devuelve un booleano</returns>
            public bool Metodo1()
            {
                return (_sPropiedad1.Length < _sPropiedad2.Length);
            }

            /// <summary>
            /// Método privado que establece el valor del miembro _iPropiedad4 <br/>
            /// a la suma de los 2 parámetros pasados.
            /// </summary>
            /// <param name="x">Primer parámetro entero</param>
            /// <param name="y">Segundo parámetro entero</param>
            private void Metodo2(Int32 x, Int32 y)
            {
                _iPropiedad4 = x + y;
            }

            /// <summary>
            /// Método público que llama al método privado Metodo2.
            /// </summary>
            /// <param name="x">Primer parámetro entero</param>
            /// <param name="y">Segundo parámetro entero</param>
            public void Metodo3(Int32 x, Int32 y)
            {
                Metodo2(x, y);           
            }

            /// <summary>
            /// Método públic que devuelve un valor doble obtenido <br/>
            /// a través de la división de dos enteros pasados como parametros.
            /// </summary>
            /// <param name="x">Primer parámetro entero</param>
            /// <param name="y">Segundo parámetro entero.</param>
            /// <returns>Devuelve un doble a partir de división de enteros.</returns>
            /// <exception cref="System.Exception">Se produce una excepción cuando intentamos dividir por cero.</exception>
            public Double Metodo4(Int32 x, Int32 y)
            {
                try
                {
                    return x / y;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
    }

    Una vez que tenemos el proyecto con los comentarios pertinentes tenemos que habilitar la opción de que al compilar se cree el fichero XML con los comentarios.

    Nota: Es muy importante tener en cuenta que si nuestro proyecto hace referencia a otros assemblies, para que se genere correctamente, dichos assemblies tienen que tener asociado su XML de documentación correspondiente, en caso contrario no garantizo que la documentación creada esté correcta.

    art9_01

    Generamos la solución y ya podemos utilizar el Sandcastle a través del programa SandcastleGUI para generarnos nuestra documentación.

    art9_02

    Como podemos observar en la figura anterior vamos rellenando la información requerida sobre nuestro proyecto.

    En la zona "General" rellenamos la primera casilla con la ruta donde se encuentra/n nuestra/s assembly/is, en la segunda casilla le decimos donde queremos que nos deje la documentación generada, la tercera casilla es para que en caso de que añadamos archivos adjuntos como imágenes las pueda encontrar, en mi caso he incluido la imagen del diagrama de la clase que he creado, en la cuarta casilla le indicamos el/los namespace/s que queremos documentar.
    En la zona "Custom" indicamos el nombre del programa, la linea de copyright y en caso de que queramos un logo su ruta.
    En la zona "Compilation" le indicamos si sigue una sintaxis de C#, VB o C++ manegado, si queremos que los ficheros generados (cuando es un Website) tengan nombres "amigables" o no (es decir, que los nombres de los htm generados tengan algún significado como F_comentarios_Class1__bPropiedad3.htm o que sea un nombre como si estuviera encriptado), si queremos que nos muestre las propiedades, métodos, etc privados (Document internals), que nos formatee a la sintaxis de C# los ejemplos, si queremos tener enlaces a la MSDN para las clases usadas del framework, y por último en qué formato lo queremos, para el ejemplo que he creado quiero un Website con plantilla Hana y que me cree el árbol de contenidos a la izquierda.
    El motivo de que haya querido un Website es que te da la posibilidad de tener un buscador.

    Una vez que hayamos puesto todas las opciones con las que queremos que se genere nuestra documentación pulsamos el botón "Start documenting" y eso hace que nos aparezca una ventana de lineas de comando haciendo un montón de cosas.

    art9_03

    Cuando se cierra la ventana de lineas de comando ya tenemos generada nuestra documentación, para la opción Website, abrimos con un navegador el archivo index.htm (que es el principal).

    art9_04

    Si navegamos a través de los constructores, métodos y propiedades que hemos comentado veremos como se ha formateado las líneas de comentario escritas en el proyecto en esta estupenda documentación. Por ejemplo, aunque no se vea muy bien, gracias a lo que hemos escrito en las etiquetas <sumary> se puede ver reflejado en la descripción de los miembros de la clase:

    art9_05

    También podemos usar etiquetas típicas de HTML (pero tratando de hacerlo como si de XML se tratara, por ejemplo la etiqueta <BR> no tiene / final, pero aquí se debe poner quedando <BR/>), e incluso podemos insertar imágenes como se puede apreciar en el siguiente dibujo (ver el código de la clase, los comentarios creados en la declaración de la clase Class1):

    art9_06

    Podemos aumentar la calidad de nuestra documentación añadiendo ejemplos prácticos (con las etiquetas <example> y <code>) y que al generarse se nos permite copiar el código como vemos en la siguiente imagen (ver el código de la clase, los comentarios creados en la declaración del segundo constructor):

    art9_07

    También se puede mostrar las excepciones que se pueden producir en un método. (ver el código de la clase, los comentarios creados en el método 4).

    art9_09

    Como os había comentado, tenemos un buscador que al poner palabras para buscar, en caso de que las encuentre nos indica donde y nos las marca en amarillo:

    art9_08

    Para que os quede mas claro, podéis crearos un proyecto, usar la clase que he definido y generar la documentación como os he ensañado, de esta forma podréis navegar por la documentación y ver el por qué de los comentarios que he usado.

    Espero que os haya parecido interesante.

    Posted: 2/4/2008 13:54 por Carmen Sanchez | con 15 comment(s) |
    Archivado en:
    SecondNug ataca de nuevo

    Hola a tod@s,

    Os recuerdo que hoy tendrá lugar el evento del mes de Abril de SecondNug sobre WCF a manos de Hadi Hariri

    El evento será a las 19:30 - 21:30 (GMT+1), y como en las anteriores ocasiones, se retransmitirá vía Web a través de Live Meeting.

    Si no tienes Live Meeting, puedes descargarlo en el siguiente enlace.

    Podéis registraros en el evento en el siguiente enlace

    No os lo podéis perder.

    Un saludo.

    Posted: 1/4/2008 11:37 por Carmen Sanchez | con 8 comment(s) |
    Archivado en:
    Más artículos Página siguiente >