January 2008 - Posts

ScreenCast : Intro AJAX ControlToolkit en VS2008
31 January 08 07:21 AM | mmonterroca | 2 comment(s)
Les dejo este screencast nivel 100 en donde veremos cómo Instalar, Configurar  y utilizar AJAX ControlToolkit dentro de Visual Studio .NET 2008
 
 
 
 
Nota: Tuve un problema ligero problema con el audio y en ocasiones se escuchan unos picos de ruido, por eso es mejor reproducirlo a un nivel de audio moderado.
La perdida de un amigo
29 January 08 09:49 PM | mmonterroca | with no comments

Hoy me acabo de enterar de la perdida de un estimado amigo, Enrique Jorquera a.k.a. Kuriaki  lo conozco desde hace casi 10 años cuando comencé a participar en las comunidades Microsoft (news://msnews.microsoft.com/) él siempre fue una persona admirada, respetada y querida por todos. Tuve la suerte de conocerlo personalmente el año pasado en un MVP Round Table en México DF aun  recuerdo muy bien el abrazo que nos dimos después de únicamente mantener una "relación" electrónica. El día de ayer lamentablemente murió de cáncer lo cual es una gran tristeza para la comunidad informática que seguía con frecuencia su post en los foros de microsoft.

¡Suerte y éxito en donde quiera que sigas amigo!

Filed under:
Métodos del Runtime en Workflow Foundation
30 January 08 03:26 AM | mmonterroca | 2 comment(s)

 

En este articulo profundizaremos un poco más acerca de los métodos disponibles en el Runtime, su sintaxis y su uso en Workflow Foundation.

La clase WorkflowRuntime

El runtime del flujo de trabajo es el intermediario entre la aplicación host y las instancias del flujo de trabajo. Aunque el flujo de trabajo es una parte muy importante de Windows Workflow Foundation, el runtime juega un papel muy importante en el ciclo de vida de los flujos de trabajo. La clase System.Workflow.Runtime.WorkflowRuntime representa el runtime del flujo de trabajo y proporciona una gran funcionalidad para manejar el ambiente del runtime. Utilizando esta clase, se tiene control absoluto de la ejecución de las instancias del flujo de trabajo y del runtime mismo. La clase System.Workflow.Runtime.WorkflowRuntime es responsable de varias tareas que son muy importantes. Una de ellas es la de el manejo de eventos del runtime que acabamos de ver en la sección anterior. Otra de ellas es la gestión del Runtime.

Gestión del Runtime

La clase WorkflowRuntime expone dos métodos públicos que se relacionan con la gestión del runtime del flujo de trabajo: StartRuntime y StopRuntime.

El método StartRuntime permite que se ejecuten dos importantes acciones. Primero, existen servicios base del runtime que siempre deben existir en un flujo de trabajo del runtime: un servicio de transacción del flujo de trabajo y un servicio planificador del flujo de trabajo. Cuando se llama a este método, se realice una validación para revisar si alguno de estos dos servicios ha sido añadido manualmente al runtime. Si no, el runtime crea instancias de default para cada tipo de servicio. La clase por default del servicio de transacción es DefaultWorkflowTransactionService, y la clase por default del servicio de planificación es DefaultWorkflowSchedulerService. Después de que los servicios se agregaron e instanciaron exitosamente al runtime, cada servicio es iniciado con el método Start. Adicionalmente a la configuración de los servicios que ocurre durante el proceso de arranque del runtime, a la propiedad IsStarted del runtime se le da el valor true, y se genera el evento Started Started.

Llamar al método StopRuntime tiene el efecto contrario. Se detienen todos los servicios, se descargan todas las instancias de flujos de trabajo, a la propiedad IsStarted se le da el valor false, y se genera el evento Stopped event. La Tabla 2 nos muestra los diferentes métodos de trabajo existentes en el workflow Runtime:

Método

Descripción

CreateWorkflow

Crea una instancia del flujo de de trabajo utilizando los parámetros especificados.

GetAllServices

Regresa todos los servicios que han sido agregados al engine del runtime del flujo de trabajo que derivan del tipo especificado.

GetLoadedWorkflows

Obtiene una colección que contiene todas las instancias de flujos de trabajo actualmente cargadas en memoria.

GetService

Obtiene un servicio del engine del runtime del flujo de trabajo que usa el tipo especificado.

GetWorkflow

Obtiene las instancia del flujo de trabajo que tiene el Guid especificado.

RemoveService

Quita el servicio especificado del engine del runtime del flujo de trabajo.

StartRuntime

Inicia el engine del runtime del flujo de trabajo y los servicios del engine del runtime del flujo de trabajo.

StopRuntime

Detiene el engine del runtime del flujo de trabajo y los servicios del engine del runtime del flujo de trabajo.

Tabla 2. Métodos del Workflow Runtime

Iniciar y manejar instancias del Workflow

Una de las tareas más importantes que el runtime puede realizar es iniciar instancias del flujo de trabajo. Adicionalmente a iniciar las instancias, el runtime expone la funcionalidad para manejarlos. Para manejar una instancia del flujo de trabajo, simplemente hay que llamar el método CreateWorkflow de la instancia WorkflowRuntime. Existen muchas formas de llamar a este método, pero el más comúnmente usado es el que usa una instancia Type, que representa el tipo de la clase de flujo de trabajo. Por ejemplo:

//MiWorkflow es la definición de clase del workflow                 
 
Type workflowType = typeof(MiWorkflow);     
 
// usa el runtime del workflow runtime para crear una instancia de MiWorkflow 
 
WorkflowInstance workflowInstance = 
 
theRuntimeInstance.CreateWorkflow(workflowType);

Aunque el código anterior crea una instancia del flujo de trabajo, en realidad no inicia el flujo de trabajo. El método Start method de la clase WorkflowInstance es la que lo hace, como se puede ver en el siguiente código:

// inicia la instancia del flujo de trabajo 
 
workflowInstance.Start(); 

 

En el siguiente ejemplo podemos ver la ejecución de los métodos StartRuntime y StopRuntime del WorkFlowRuntime junto con el método Start para la instancia del flujo de trabajo:

Main() 
 
{ 
 
string connectionString = "Initial Catalog=SqlPersistenceService;Data Source=localhost;Integrated Security=SSPI;"; 
 
 
 
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime()) 
 
{ 
 
ExternalDataExchangeService dataService = new ExternalDataExchangeService(); 
 
workflowRuntime.AddService(dataService); 
 
dataService.AddService(expenseService); 
 
 
 
workflowRuntime.AddService(new SqlWorkflowPersistenceService(connectionString)); 
 
workflowRuntime.StartRuntime(); 
 
 
 
workflowRuntime.WorkflowCompleted += OnWorkflowCompleted; 
 
workflowRuntime.WorkflowTerminated += OnWorkflowTerminated; 
 
 
 
Type type = typeof(EjemploWorkflow1); 
 
WorkflowInstance workflowInstance = workflowRuntime.CreateWorkflow(type); 
 
workflowInstance.Start(); 
 
 
 
waitHandle.WaitOne(); 
 
 
 
workflowRuntime.StopRuntime(); 
 
} 
 
}
Eventos del Runtime en Workflow Foundation
30 January 08 03:25 AM | mmonterroca | 2 comment(s)

 

En este articulo profundizaremos un poco más acerca del Runtime Engine, los diferentes eventos del Runtime, su sintaxis y su uso en Workflow Foundation.

Runtime Engine

La arquitectura de Windows Workflow Foundation consta de seis partes principales, el Runtime Engine es una de ellas. El Runtime Engine es una librería que ejecuta flujos de trabajo. El Runtime Engine también provee otros servicios, como mecanismos para comunicarse con software fuera del flujo de trabajo. Todos los flujos de trabajos dependen del Windows Workflow Foundation Runtime Engine. Este motor ejecuta cada flujo de trabajo y maneja su estado a lo largo de su tiempo de vida. El Windows Workflow Foundation Runtime es una librería; por lo tanto, debe ser ejecutado en algún proceso host. En vez de proveer un host requerido, Windows Workflow Foundation le permite al Runtime (y a cualquier flujo de trabajo que ejecute) ser alojado en cualquier proceso Windows, desde una simple aplicación de consola de Windows o una aplicación de formulario, hasta un servidor complejo diseñado teniendo en cuenta el ambiente de flujo de trabajo.

Windows Workflow Foundation cuenta con un conjunto de servicios que le permiten al Runtime ejecutarse dentro de ASP.NET, aunque los vendedores independientes de software y los usuarios finales son libres de crear sus propias aplicaciones contenedoras de flujo de trabajos para aplicaciones existentes.

Al ser Windows Workflow Foundation un Framework para flujos de trabajo en vez de un producto independiente, y al soportar este tipo de diversidades, se convierte en una meta explícita para sus creadores. A pesar de que cada host usa el mismo Runtime Engine, cada uno debe proveer un conjunto de servicios Runtime. Estos servicios brindan soporte para persistir el estado de un flujo de trabajo, rastrear su ejecución, usar transacciones, etc.

Un flujo de trabajo puede ser de larga duración, ya que podría ejecutarse durante horas, días o semanas, y el Runtime de Windows Workflow Foundation podría apagarse durante un flujo de trabajo, y persistentemente almacenaría su estado si hubiera estado inactivo por un período de tiempo.

La decisión de descargar el flujo de trabajo se puede lanzar porque éste se encuentra bloqueado esperando un evento externo; esta decisión es tomada típicamente por el Runtime. Para escribir estados del flujo de trabajo en el disco, el Runtime depende del servicio de persistencia proporcionado por su proceso host.

Los eventos del flujo de trabajo son procesados por el Runtime a través de los delegados de manejo de eventos.

WWF_Eventos_1

¿Por qué son importantes los Runtime Events?

Porque proporcionan un mecanismo para hacer un seguimiento del ciclo de vida del flujo de trabajo, por ejemplo cuando se crea un flujo de trabajo, cuando finaliza el mismo flujo, etc. Otro beneficio de manejar eventos del Runtime es que proporcionan un mecanismo para dar seguimiento a todas las instancias del flujo de trabajo. De esta forma podemos determinar cuántos fueron los flujos de trabajo fueron creados, abortados, terminados, etc. Entre los eventos que se ejecutan del lado del workflowRuntime a los que se puede suscribir son:

Del tipo:

  • EventHandler<WorkflowRuntimeEventArgs>
  • EventHandler<WorkflowEventArgs>

Del motor:

  • Started
  • Stopped

De las instancias:

  • WorkflowCreated/Started/Stopped
  • WorkflowAborted/Terminated/Completed
  • WorkflowIdled/Loaded/Persisted/Unloaded

Eventos de Flujo de Trabajo

Los eventos del flujo de trabajo son procesados por el Runtime a través de los delegados de manejo de eventos. Estos eventos son generados/levantados por el Runtime del flujo de trabajo y no por la instancia del flujo de trabajo. Asimismo, tampoco son modelados como parte de la definición de flujo de trabajo. Los eventos enviados por el Runtime del flujo de trabajo contiene el identificador de la instancia del flujo de trabajo que generó el evento. La Tabla 1 nos muestra los diferentes eventos de flujo de trabajo existentes:

Eventos de flujo de trabajo

Descripción

ServicesExceptionNotHandled

Generado cuando la instancia del flujo de trabajo no puede manejar la excepción interna

Started

Generado cuando se inicia el runtime

Stopped

Generado cuando se detiene el runtime

WorkflowAborted

Generado cuando se aborta la instancia del flujo de trabajo

WorkflowCompleted

Generado cuando se completa la instancia del flujo de trabajo

WorkflowCreated

Generado cuando se crea la instancia del flujo de trabajo

WorkflowIdled

Generado cuando la instancia del flujo de trabajo está inactiva(por ejemplo: Delay o EventSink)

WorkflowLoaded

Generado cuando la instancia del flujo de trabajo se carga en memoria (por ejemplo: re-hydrated)

WorkflowPersisted

Generado cuando la instancia del flujo de trabajo tiene persistencia

WorkflowResumed

Generado cuando la instancia del flujo de trabajo se reanuda después de ser suspendida

WorkflowStarted

Generado cuando se inicia la instancia del flujo de trabajo

WorkflowSuspended

Generado cuando el runtime suspende la instancia del flujo de trabajo

WorkflowTerminated

Generado cuando el runtime o internamente se termina la instancia del flujo de trabajo

WorkflowUnloaded

Generado cuando la instancia del flujo de trabajo se descarga de memoria (por ejemplo: Hydrated)

Tabla 1. Eventos de Flujo de Trabajo

 

En el siguiente ejemplo podemos ver la implementación del evento WorkflowCompleted del WorkFlowRuntime:

private void ApplicationInitMethod() 
 
{ 
 
WorkflowRuntime workflowRuntime = new WorkflowRuntime(); 
 
workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>( 
 
workflowRuntime_WorkflowCompleted); 
 
} 
 
 
 
void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e) 
 
{ 
 
MessageBox.Show("Se completó el flujo de trabajo"); 
 
} 

 

En el siguiente ejemplo podemos ver la implementación del evento WorkflowCreated del WorkFlowRuntime:

private void ApplicationInitMethod() 
 
{ 
 
WorkflowRuntime workflowRuntime = new WorkflowRuntime(); 
 
workflowRuntime.WorkflowCreated += new EventHandler<WorkflowCompletedEventArgs>( 
 
workflowRuntime_WorkflowCreated); 
 
} 
 
 
 
void workflowRuntime_WorkflowCreated(object sender, WorkflowCompletedEventArgs e) 
 
{ 
 
MessageBox.Show("Se creó el flujo de trabajo"); 
 
} 
Filed under: , ,
Conceptos básicos de programación 3d en WPF
29 January 08 07:42 PM | mmonterroca | 1 comment(s)

 

En este articulo conoceremos los conceptos básico de programación en tercera dimensión para Windows Presentation Foundation

 

Durante muchos años el escribir programas que generasen modelos en 3D estaba limitado a aquellas personas que supieran tecnologías como OpenGL o DirectX y lenguajes no siempre muy sencillos de usar como C++. En WPF se inicia un nuevo panorama en la programación de modelos tridimensionales de que con relativa facilidad es posible crear modelos en 3D utilizando clases predefinidas que trae el .NET Framework desde luego pudiendo ser uso de los lenguajes de programación como C# y VB o o bien utilizando el XAML.

El sistema de gráficos de tercera dimensión de Windows Presentation Foundation se encuentra completamente integrado al sistema de graficos 2D y todos los elementos y primitivas visuales que son válidos en el entorno 2D también serán válidos en el trabajo en tercera dimensión, por ejemplo sabemos que para generar un gradiente utilizamos el elemento <LinearGradientBrush> . De la misma manera podemos utilizar la misma técnica para generar una textura que tiene cualquier objeto generado en tercera dimensión con el mismo método sin necesidad de aprender algo nuevo.

Esto representa una gran ventaja para los desarrolladores toda vez que no es necesario aprender un lenguaje diferente u objetos distintos para manejo de gráficos de tercera dimensión si no que es posible reutilizar todo el conocimiento adquirido con el dibujo 2D y simplemente aprender a algunos conceptos nuevos propios del modelo de 3D.

Generando un objeto 3D con WPF

1) El elemento ViewPort3D nos brinda la capacidad de dibujar una escena tridimensional en una superficie de dos dimensiones.

Este elemento expone la colección Children que es una colección de objetos ModelVisual3D dentro de los cuales implementaremos nuestras escenas tridimensionales. El código requerido es el siguiente

XAML:

<Viewport3D ClipToBounds="True" Width="150" Height="150">
 
<Viewport3D.Children>
 
<ModelVisual3D>
 
</ModelVisual3D> 
 
</Viewport3D.Children>
 
</Viewport3D>
 

2) Dentro del elemento ModelVisual3D podemos especificar cualquier dibujo que deseemos. Sin embargo a diferencia de los gráficos en dos dimensiones donde existen primitivas predefinidas para dibujar objetos como elipses o rectángulos, en el mundo de 3D únicamente contamos con una clase denominada MeshGeometry3D en la cual es posible especificar un conjunto de vértices de triángulos mediante la propiedad Positions. Esto se debe a que cualquier dibujo tridimensional es posible describirlo con triángulos. Recordemos lo que sucede en los juegos de video: cuando hacemos un acercamiento fuerte alguna escena tridimensional podemos apreciar que las puntas y contornos de los objetos se tornan triangulares, esto se debe a que muchos objetos de los videojuegos, al igual que en WPF, son conjuntos de triángulos, que mediante su composición dan la sensación de un objeto tridimensional.

Nota: En el caso de WPF en .NET 3.5 se agrega un nuevo elemento llamado Viewport2DVisual3D que permite de una manera más sencilla generar una vista tridimensional a partir de la descripción de un objeto 2D.

Regresando a nuestro ejemplo una vez que hemos definido nuestra superficie de dibujo procederemos a utilizar la propiedad ModelVisual3D.Content para dentro de la misma especificar un MeshGeometry3D, en este caso con las posiciones establecidas estaremos generando un cuadrado

XAML

<ModelVisual3D.Content>
 
<GeometryModel3D>
 
<GeometryModel3D.Geometry>
 
<MeshGeometry3D
 
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " />
 
</GeometryModel3D.Geometry>
 
</GeometryModel3D> 
 
</ModelVisual3D.Content>

3) A diferencia de lo que sucede con los objetos 2D donde el concepto de luz no existe, en 3D es indispensable especificar una fuente de luz debido a que si no existe ésta simplemente nuestro objeto no será visible de la misma manera que sucede en la misma vida real. Esto significa debemos de especificar el lugar que estará irradiando la luz y el tipo de material del cual se compone nuestro objeto es decir si éste es reflejante o no.

WPF especifica tres tipos de materiales el SpecularMaterial que refleja la luz de tal manera que el objeto parece brillar, el EmissiveMaterial que refleja la luz y el DiffuseMaterial que no refleja la luz.

En nuestro ejemplo utilizaremos el material DiffuseMaterial. Para especificar el tipo de material del cual se compone nuestro Mesh hacemos uso del siguiente código dentro de GeometryModel3D:

XAML

<GeometryModel3D.Material>
 
<DiffuseMaterial Brush="Red" ></DiffuseMaterial>
 
</GeometryModel3D.Material>

4) Dentro del mundo de tercera dimensión los objetos cambian de apariencia desde el punto de vista de quien observa al objeto. En WPF especificamos este punto de vista haciendo uso de los objetos que heredan de ProjectionCamera.

Controlamos a nuestras cámaras como si en verdad la cámara estuviera posicionada en el espacio, la propiedad Position es del tipo Point3D y especifica las coordenadas en la cual se encuentra la cámara.

XAML:

<Viewport3D.Camera>
 
<PerspectiveCamera Position="0,0,2"/>
 
</Viewport3D.Camera>

Si nosotros ejecutamos el código que llevamos hasta el momento veremos lo siguiente.

 

Aquí antes que nada podemos ver que se generó un cuadrado derivado de los vértices que se le especificaron al elemento MeshGeometry3D. Como aún no hacemos ninguna transformación de nuestro objeto no podemos ver la profundidad que tiene. Añadiremos una transformación posteriormente. Otro aspecto que podemos resaltar es que a pesar de que el material especificado con DiffuseMaterial fue de color Red estamos viendo que nuestro programa muestra el cuadrado en color negro. Esto se debe a que aún no hemos especificado la manera en la cual llega la luz al objeto, estos pasos los haremos a continuación.

5) Para agregar una fuente de luz a nuestra escena, dentro de ViewPort3D.Children especificaremos el siguiente código

XAML:

<ModelVisual3D>
 
<ModelVisual3D.Content>
 
<DirectionalLight Color="White" Direction="-0.5,-0.1,-0.5" />
 
</ModelVisual3D.Content>
 
</ModelVisual3D> 

6) Al ejecutar el código del listado previo podemos ver que ahora nuestro objeto está reflejando la luz y por lo tanto mostrando el color que se le especificó previamente.

7) Procederemos ahora generar una transformación dentro del elemento GeometryModel3D que nos permitirá ver a nuestro objeto en profundidad y de esta manera percibir el efecto de tercera dimensión. Para realizar este objetivo es necesario hacer uso de la clase RotateTransform3D que funciona de una manera similar a su equivalente bidimensional, pero a diferencia del segundo, en el primero hacemos uso de 3 dimensiones para rotar al elemento deseado. A continuación se muestra el uso de este objeto

XAML:

<GeometryModel3D.Transform>
 
<RotateTransform3D>
 
<RotateTransform3D.Rotation>
 
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
 
</RotateTransform3D.Rotation>
 
</RotateTransform3D>
 
</GeometryModel3D.Transform> 

8) Para finalizar nuestro ejemplo animaremos la propiedad Angle de la transformación. La sintaxis para hacer animación en elementos 3D es exactamente la misma que para los objetos bidimensionales. (ver capítulo “Animación”). Con esta animación veremos que el objeto está moviéndose de una manera circular.

El código requerido es el siguiente:

XAML

<Viewport3D.Triggers>
 
<EventTrigger RoutedEvent="Viewport3D.Loaded">
 
<BeginStoryboard>
 
<Storyboard>
 
<DoubleAnimation From="1" To="360" Duration="0:0:03" AccelerationRatio="1" RepeatBehavior="Forever" 
 
Storyboard.TargetProperty="(Viewport3D.Children)[1].(ModelVisual3D.Content).(GeometryModel3D.Transform).(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"></DoubleAnimation>
 
</Storyboard>
 
</BeginStoryboard>
 
</EventTrigger>
 
</Viewport3D.Triggers>
 

El código completo de todo el ejemplo es el siguiente:

XAML

<Grid>
 
<Viewport3D ClipToBounds="True" Width="150" Height="150">
 
<Viewport3D.Camera>
 
<PerspectiveCamera Position="0,0,2"/>
 
</Viewport3D.Camera>
 
<Viewport3D.Children>
 
<ModelVisual3D>
 
<ModelVisual3D.Content>
 
<DirectionalLight Color="White" Direction="-0.5,-0.1,-0.5" />
 
</ModelVisual3D.Content>
 
</ModelVisual3D> 
 
<ModelVisual3D>
 
<ModelVisual3D.Content>
 
<GeometryModel3D>
 
<GeometryModel3D.Geometry>
 
<MeshGeometry3D
 
Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " />
 
</GeometryModel3D.Geometry>
 
<GeometryModel3D.Material>
 
<DiffuseMaterial Brush="Red" ></DiffuseMaterial>
 
</GeometryModel3D.Material>
 
<GeometryModel3D.Transform>
 
<RotateTransform3D>
 
<RotateTransform3D.Rotation>
 
<AxisAngleRotation3D Axis="0,3,0" Angle="40" />
 
</RotateTransform3D.Rotation>
 
</RotateTransform3D>
 
</GeometryModel3D.Transform> 
 
</GeometryModel3D> 
 
</ModelVisual3D.Content>
 
</ModelVisual3D> 
 
</Viewport3D.Children>
 
<Viewport3D.Triggers>
 
<EventTrigger RoutedEvent="Viewport3D.Loaded">
 
<BeginStoryboard>
 
<Storyboard>
 
<DoubleAnimation From="1" To="360" Duration="0:0:03" AccelerationRatio="1" RepeatBehavior="Forever" 
 
Storyboard.TargetProperty="(Viewport3D.Children)[1].(ModelVisual3D.Content).(GeometryModel3D.Transform).(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)"></DoubleAnimation>
 
</Storyboard>
 
</BeginStoryboard>
 
</EventTrigger>
 
</Viewport3D.Triggers> 
 
</Viewport3D>
 
</Grid>
 

 

Articulo Publicado en http://desarrollador.redusers.com/

Filed under: , ,
Distintos tipos de Actividades Predefinidas
29 January 08 07:47 AM | mmonterroca | 3 comment(s)

Distintos tipos de Actividades Predefinidas

Workflow Foundation incluye una gran variedad de actividades predefinidas que podemos utilizar al crear nuestros propios flujos de trabajo. En este articulo veremos algunas de las actividades más destacables incluidas en esta plataforma.

Code

Clase: System.Workflow.Activities.CodeActivity

La actividad Code es una de las actividades más usadas en Workflow Foundation, ya que nos permite ejecutar cualquier tipo de código escrito dentro de un método. Su propiedad más importante es ExecuteCode la cual establece el nombre del método que queremos que se ejecute. En algunos capítulos hemos visto incluso el uso de esta actividad y su importancia que tiene al desarrollar flujos de trabajo. La siguiente figura muestra el resultado de un flujo de trabajo que utiliza esta actividad la cual ejecutará el método MetodoAEjecutar(), siendo el código de ese método el siguiente:

private void MetodoAEjecutar(object sender, EventArgs e) 
 
{ 
 
Console.WriteLine("Hola Workflow Foundation"); 
 
} 
 

Sequence

Clase: System.Workflow.Activities.SecuenceActivity

La actividad Sequence nos permite ejecutar otras actividades en un orden específico, ya que asimismo esta actividad es un contenedor de otras actividades. Un buen ejemplo de una actividad Sequence son los flujos de trabajo de tipo Sequential Workflow, en donde podemos definir diversas actividades para que se ejecuten de manera ordenada o secuencial.

Los flujos de trabajo de tipo Sequential Workflow son instancias de la clase System.Workflow.Activities.SequentialWorkflowActivity, la cual a su vez hereda de la clase System.Workflow.Activities.SequenceActivity.

La siguiente figura muestra el diseñador de Workflow Foundation con una actividad Sequence con tres actividades de tipo Code. El código de esas actividades es el siguiente:

private void Metodo1(object sender, EventArgs e) 
 
{ 
 
Console.WriteLine("Code 1"); 
 
} 
 
 
 
private void Metodo2(object sender, EventArgs e) 
 
{ 
 
Console.WriteLine("Code 2"); 
 
} 
 
 
 
private void Metodo3(object sender, EventArgs e) 
 
{ 
 
Console.WriteLine("Code 3"); 
 
} 
 

 

Por otro lado, al ejecutar el flujo de trabajo de la figura anterior obtenemos el resultado de la siguiente figura. Nótese como efectivamente el código es ejecutado en el orden establecido.

WWF_Actividades_b

Parallel

Clase: System.Workflow.Activities.ParallelActivity

La actividad Parallel como su nombre lo indica permite a un flujo de trabajo ejecutar paralelamente dos o más actividades. Parallel hace uso de la actividad Sequence para definir la serie de actividades que requieren ejecutarse en cada ramificación que definamos. La siguiente figura muestra un flujo de trabajo que implementa esta actividad con cuatro ramificaciones que incluyen cuatro actividades de tipo Code (codeActivity1, codeActivity2, codeActivity3, codeActivity4). El código de los métodos relacionados con esas actividades es el siguiente:

WWF_Actividades_2

 

 

El resultado de la ejecución de este flujo de trabajo será el siguiente:

WWF_Actividades_3 

Es importante aclarar que si bien la actividad Parallel define actividades que se ejecutarán de manera paralela no significa que se ejecutarán al mismo tiempo. Esto obedece a que Workflow Foundation asigna un solo hilo de ejecución para cada instancia de un flujo de trabajo. Esto es por diseño.

 

Delay

Clase: System.Workflow.Activities.DelayActivity

Esta actividad permite definir un retraso de tiempo. Su propiedad más importante es TimeoutDuration la cual especifica la duración en tiempo de ese retraso. La siguiente figura muestra el resultado de agregar esta actividad a la segunda rama del ejemplo de la actividad Parallel, con un retraso de 10 segundos. Podemos observar como efectivamente el retraso de tiempo provoca que el mensaje de codeActivity2 sea desplegado hasta el último lugar.

WWF_Actividades_4

 

While

Clase: System.Workflow.Activities.WhileActivity

La actividad While nos permite ejecutar una serie de actividades de manera cíclica, usando un método que funcione como expresión condicional. Su propiedad más importante es Condition con la cual precisamente definimos el tipo de condición a utilizar (Code Condition o Declarative Rule Condition). En el caso de seleccionar Code Condition necesitamos definir el nombre del método relacionado que fungirá como condicionante para que la actividad While continúe ejecutando iterativamente. El método relacionado con esta actividad debe tener la siguiente signatura:

void NombreDelMetodo(object, ConditionalEventArgs) 

ConditionalEventArgs tiene la propiedad Result de tipo bool. Esta propiedad le indica al runtime de Workflow Foundation si la condición es verdadera o falsa. En este caso para la actividad While si Result es true significa que debe continuar su ejecución de manera cíclica. Si Result es false el ciclo de While es finalizado y continúa la ejecución de la siguiente actividad definida después de While. Veamos un ejemplo de esta actividad.

La siguiente figura muestra el diseñador de Workflow Foundation con una actividad While, la cual contiene una actividad Code. El código relacionado con la actividad Code es el siguiente:

int contador = 1; 
 
 
 
private void Metodo1(object sender, EventArgs e) 
 
{ 
 
Console.WriteLine(contador); 
 
contador++; 
 
} 
 

WWF_Actividades_5

Es necesario hacer notar que hemos definido una variable a nivel de clase llamada int contador. Esta variable nos servirá para desplegar su valor en la consola por cada ejecución iterativa de la actividad Code dentro de While. Para la actividad While hemos establecido que Condition es de tipo Code Condition, y hemos definido el método ChecaCondicion() el cual se encargará de evaluar si la condición ha sido alcanzada. El código de ChecaCondicion() es el siguiente:

private void ChecaCondicion(object sender, ConditionalEventArgs e) 
 
{ 
 
e.Result = contador<=20?true:false; 
 
} 

Si analizamos el código del método ChecaCondicion() podemos observar que estamos evaluando que la actividad While seguirá iterando siempre y cuando la variable llamada contador sea igual o menor que 20. Ya que la variable contador se inicializa con el valor de 1, tal y como esperamos, la consola desplegará los números del 1 al 20 ya que al llegar al 20 la condición evalúa a falsa y While alcanza su fin. Esto lo podemos corroborar en la siguiente figura:

WWF_Actividades_6

Throw

Clase: System.Workflow.ComponentModel.ThrowActivity

La actividad Throw nos permite lanzar excepciones dentro de un flujo de trabajo en Workflow Foundation. Esta actividad nos será de mucha utilidad cuando detectemos que el comportamiento o valores dentro de nuestro flujo de trabajo han alcanzado un estado inconsistente y por ello necesitemos parar la ejecución del flujo. Su propiedad más importante es FaultType, la cual indica qué tipo de excepción es la que arrojará esa actividad.

Para poder demostrar el uso de la actividad Throw, usaremos el mismo flujo de trabajo usado para la actividad While, sin embargo después (abajo) de la actividad While arrastraremos la actividad Throw de la caja de herramientas y la colocaremos en el diseñador. La siguiente figura muestra la caja de diálogo "Browse and Select a .NET Type", en donde podemos buscar y definir el tipo de excepción que la actividad Throw arrojará. Para este ejemplo usaremos la excepción de tipo System.ApplicationException la cual está implementada en mscorlib.

WWF_Actividades_7

La segunda propiedad importante para esta actividad es Fault, la cual nos permite definir una propiedad o campo para ligar la excepción. La siguiente figura muestra la caja de diálogo "Bind 'Fault' to an activity's property". En esta caja de diálogo podemos seleccionar un miembro existente o crear un nuevo miembro. En nuestro caso en este ejemplo crearemos un nuevo miembro ya que no hemos escrito código hasta el momento. Podemos seleccionar que la excepción se ligue a una variable o a una propiedad, en nuestro caso usaremos un campo llamado workflow_exception.

WWF_Actividades_8

Una vez definida y configurada la actividad Throw, veamos en la siguiente figura cuál es el resultado de la ejecución de este flujo de trabajo.

WWF_Actividades_9

Como podemos observar, después de desplegar los valores del contador la consola nuestra el mensaje de error relacionado con esa excepción. Ahora bien, podemos darnos cuenta que la ejecución del flujo de trabajo es suspendida gracias a que se está arrojando una excepción de tipo ApplicationException. En la siguiente parte veremos la actividad FaultHandler la cual nos permite capturar cualquier tipo de excepción y manejarla apropiadamente.

FaultHandler

Clase: System.Workflow.ComponentModel.FaultHandlerActivity

La actividad FaultHandler nos permite manejar apropiadamente las excepciones que sean arrojadas por las actividades Throw dentro de nuestros flujos de trabajo en Workflow Foundation. Para demostrar su uso continuaremos usando el proyecto de flujo de trabajo usado en la demostración de la actividad Throw. En un flujo de trabajo podemos definir uno o más actividades de tipo FaultHandler para definir las actividades que deben ser ejecutadas al estar capturando la excepción. Para realizar esto necesitamos cambiar la vista de nuestro diseñador para desplegar la lista de FaultHandlers. Esto lo logramos haciendo clic en la lista desplegable que se muestra al acercar el cursor a la fecha verde de inicio de nuestro flujo de trabajo, tal y como lo muestra la siguiente figura:

WWF_Actividades_10

Al cambiarnos de vista podemos observar que el diseñador de Workflow Foundation crea una actividad FaultHandlersActivity (nótese el nombre en plural), la cual es un contenedor de actividades de tipo FaultHandlerActivity. En esta actividad podemos arrastrar y colocar una o más actividades de tipo FaultHandler para así definir en cada una la serie de actividades que deseamos que se ejecuten al estar manejando la excepción. La actividad FaultHandler tiene la propiedad FaultType, la cual nos sirve para definir el tipo de excepción que esta actividad puede capturar. La siguiente figura muestra el diseñador con una actividad de tipo FaultHandler a la que se le ha definido la propiedad FaultType como System.ApplicationException (para efectivamente capturar la excepción que arroja Throw) y dentro de esta actividad se ha colocado una actividad de tipo Code con el siguiente código relacionado:

private void ErrorManejado(object sender, EventArgs e) 
 
{ 
 
Console.WriteLine("Error manejado!"); 
 
} 

WWF_Actividades_11

Como podemos deducir, al ejecutar el flujo de trabajo la actividad FaultHandler captura la excepción arrojada por la actividad Throw y despliega efectivamente el mensaje "Error manejado!" en la consola, en vez de desplegar el mensaje por defecto de la excepción. Vale la pena mencionar que cada actividad FaultHandler podría tener una o más actividades relacionadas. El resultado de la ejecución de este flujo de trabajo es mostrado en la siguiente figura:

WWF_Actividades_12

Articulo Publicado en http://desarrollador.redusers.com/

Filed under: , , ,
¡Buen comienzo!
23 January 08 07:29 PM | mmonterroca | 2 comment(s)

Comenzamos el año con muy buenas noticias la primera y más importante es la entrada de Alfredo Ceballos a DevWorx quien nos estará apoyado en varios proyectos estratégicos que estamos teniendo (Performance Point, MOSS, BizTalk etc) ¡Bienvenido Alfredo!

 

Otra noticia no menos importante es que ¡Ya tenemos logo oficial!  algún parecido con Visual CSharp? Dev(Worx); :D

 

 

Y por ultimo, pues es el rediseño de nuestro portal colaborativo en base a los colores de nuestro logotipo, espero les guste

 

Saludos!

Filed under: ,
Actividades personalizadas en Windows WorkFlow Foundation (WWF)
23 January 08 04:58 AM | mmonterroca | 2 comment(s)

 

En este articulo aprenderemos los pasos básicos para crear una actividad personalizada dentro den WWF

 

Actividades personalizadas

Windows WorkFlow Foundation provee varias actividades preestablecidas, como Code activity, Compensate Activity, Delay Activity etc sin embargo dichas actividades difícilmente  pueden contemplar todas las diferentes actividades de negocio o técnicas que necesitemos implementar. Es por esto que WWF nos permite crear nuestras propias actividades heredando de diferentes clases base (solo se listan las más importantes):

 

Clase Base

Descripción

Activity

Todas las actividades heredan de ésta clase

SequenceActivity

Es utilizada para crear una actividad compuesta que contiene actividades hijas que son ejecutadas en forma secuencial

StateActivity

Es utilizado dentro de un StateMachine WorkFlow y expone eventos que permiten la inicialización de la actividad a un estado seleccionado

CompositeActivity

Permite crear una actividad compuesta sin la posibilidad de tener actividades hijas

 

 

Tabla 1. Principales clases base para crear una actividad personalizada

 

En este capítulo crearemos una actividad que nos permita realizar el envió de un correo electrónico para lo cual, solo necesitamos heredar de la clase base "Activity" ya ésta clase nos provee toda la funcionalidad básica necesaria.

 

Para crear la actividad seguiremos los siguientes pasos

  • Abrir Visual Studio 2008
  • En el menú seleccionar File -> New -> Proyect
  • En Proyect Types seleccionar Workflow
  • En la lista de plantillas seleccionar WorkFlow Activity Library
  • En Name escribir EnviarCorreoActivity
  • En el Solution Explorer seleccionar Activity1 y dar clic con el botón derecho del ratón y seleccionar Rename, en el nuevo nombre escribir EnviarCorreoActivity.cs y presionar enter
  • En la advertencia de un clic en Yes
  • En la clase renombrada dar un clic nuevamente con el botón derecho del raton y seleccionar View Code
  • Cambiar la clase de la cual se está heredando SequenceActivity por Activity

 

En este punto, debemos de tener una clase similar a la siguiente

 

 

using System;
 
using System.ComponentModel;
 
using System.ComponentModel.Design;
 
using System.Collections;
 
using System.Drawing;
 
using System.Linq;
 
using System.Workflow.ComponentModel.Compiler;
 
using System.Workflow.ComponentModel.Serialization;
 
using System.Workflow.ComponentModel;
 
using System.Workflow.ComponentModel.Design;
 
using System.Workflow.Runtime;
 
using System.Workflow.Activities;
 
using System.Workflow.Activities.Rules;
 
 
 
namespace EnviarCorreoActivity
 
{
 
      public partial class EnviarCorreoActivity: Activity
 
      {
 
            public EnviarCorreoActivity()
 
            {
 
                  InitializeComponent();
 
            }
 
      }
 
}
 

 

 

Para realizar el envió de correo electrónico necesitamos que la actividad exponga 4 propiedades dependientes "Para" "De" "Asunto" y "Cuerpo" para ellos utilizaremos el método Register de la clase DependencyProperty

 

public static DependencyProperty DeProperty = DependencyProperty.Register("De", typeof(string), typeof(EnviarCorreoActivity));
 
 
 
        public static DependencyProperty ParaProperty = DependencyProperty.Register("Para", typeof(string), typeof(EnviarCorreoActivity));
 
 
 
        public static DependencyProperty AsuntoProperty = DependencyProperty.Register("Asunto", typeof(string), typeof(EnviarCorreoActivity));
 
 
 
        public static DependencyProperty CuerpoProperty = DependencyProperty.Register("Cuerpo", typeof(string), typeof(EnviarCorreoActivity));

 

 

Ahora crearemos las propiedades físicas que se encargaran de realizar la persistencia u obtención  de la información proporcionada, para ello hay que utilizar los métodos SetValue y GetValue y la clase base.

public string De
 
        {
 
 
 
            get
 
            {
 
                return Convert.ToString(base.GetValue(DeProperty));
 
            }
 
 
 
            set
 
            {
 
                base.SetValue(DeProperty, value);
 
            }
 
 
 
        }
 
 
 
        public string Para
 
        {
 
            get
 
            {
 
                return Convert.ToString(base.GetValue(ParaProperty));
 
            }
 
 
 
            set
 
            {
 
                base.SetValue(ParaProperty, value);
 
            }
 
        }
 
 
 
        public string Asunto
 
        {
 
            get
 
            {
 
                return Convert.ToString(base.GetValue(AsuntoProperty));
 
            }
 
 
 
            set
 
            {
 
                base.SetValue(AsuntoProperty, value);
 
            }
 
        }
 
 
 
        public string Cuerpo
 
        {
 
            get
 
            {
 
                return Convert.ToString(base.GetValue(CuerpoProperty));
 
            }
 
 
 
            set
 
            {
 
                base.SetValue(CuerpoProperty, value);
 
            }
 
        }
 

Por último sobrescribiremos el método Execute de la clase base, este método es llamado cuando la actividad es requerida para su ejecución, dentro de este método realizaremos el envió del correo electrónico. Como resultado de la ejecución regresaremos el valor Closed solo  en caso de que el envió sea exitoso en caso contrario será Faulting este valor es tomado de la enumeración ActivityExecutionStatus

 

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
 
        {
 
            try
 
            {
 
                System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient("devworx.com.mx");
 
                smtpClient.Credentials = new System.Net.NetworkCredential("misael.monterroca@devworx.com.mx", "password");
 
                smtpClient.Send(De, Para, Asunto, Cuerpo);
 
                return ActivityExecutionStatus.Closed;
 
            }
 
            catch (Exception ex)
 
            {
 
                string logInterno = ex.Message;
 
                return ActivityExecutionStatus.Faulting;
 
            }
 
        }
 

 

 

 

Ahora crearemos un WorkFlow para poder probar la actividad creada, para ellos realizaremos las siguientes actividades:

 

  • En el menú de Visual Studio 2008 seleccionaremos File -> Add - New Project
  • En las plantillas de proyecto seleccionaremos Sequential WorkFlow Console Application
  • En name escribiremos Flujo de Prueba
  • En el Solution Explorer seleccionaremos el proyecto recién agregado y con el botón derecho del ratón seleccionaremos la opción Add Reference
  • Seleccionar la pestaña Projects
  • Seleccionar el proyecto EnviarCorreoActivity y dar un clic en OK

Con los pasos anteriores podremos utilizar la actividad dentro del WorkFlow además de que la actividad será posicionada dentro de la barra de herramientas de Visual Studio 2008

 


Imagen 1. Actividad dentro de la barra de herramientas

 

El siguiente paso será arrastrar la actividad EnviarCorreoActivity al diseñador de WorkFlow, seleccionaremos la actividad previamente agregada y presionaremos la tecla F4 para mostrar la ventana de propiedades

 

Imagen 2. La ventana de propiedades mostrando las propiedades definidas para nuestra actividad

 

Con este procedimiento hemos creado nuestra primera actividad personalizada solo basta con especificar las propiedades e iniciar el flujo para poder probar que la actividad se está ejecutando de manera correcta.

 

Articulo Publicado en http://desarrollador.redusers.com/

Controles en WPF
13 January 08 08:33 PM | mmonterroca | 5 comment(s)

En este articulo aprenderemos a utilizar los controles más comunes en Windows Presentation Foundation

 

Controles en WPF

 Existen diferentes tipos de controles en WPF y aún cuando la mayoría son utilizados para tener interacción con el usuario, existen algunos que permiten organizar el posicionamiento de los controles, realizar tareas en segundo plano, incrustar video, etc. Cuando creamos un nuevo proyecto del tipo “Windows Application (WPF)” Visual Studio 2008 nos presentara en la barra de herramientas los diferentes controles de WPF agrupados por las siguientes categorías: 

·         Controles comunes

·         Contenedores comunes

·         Menús y Barras de herramientas

·         Todos los controles

·         Todos los contenedores

 

Controles Comunes

Como su nombre lo indica, son los controles que comúnmente son más utilizados al momento de desarrollar una aplicación:

 

·         Grid

·         Button

·         CheckBox

·         ComboBox

·         Image

·         InkCanvas

·         InkPresenter

·         Label

·         ListBox

·         PasswordBox

·         RadioButton

·         Slider

·         TextBox

 

En este capítulo solo haremos referencia a los controles Grid, Label, Textbox, ComboBox,RadioButton e Image ya que son los controles que exponen una funcionalidad típica en una aplicación.

 

Grid

El control Grid pertenece a la  categoría Contenedores Comunes y como cualquier control de su misma categoría, permite definir el posicionamiento de los diferentes controles que se encuentren dentro de elemento Window. Si no definiéramos un control de LayOut perderíamos la posibilidad de representar gráficamente varios controles como lo demuestra el siguiente ejemplo.

XAML

<Window x:Class="Users_SimpleControls.Window1"
 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 
    Title="Users_SimpleControls" Height="300" Width="300"
 
    >
 
     <Button Height="200" Width="200">Hola</Button> 
 
</Window> 

En el ejemplo anterior, se está creando una ventana con un alto y ancho de 300 pixeles y directamente como un elemento hijo, se le está agregando un control del tipo Button. 

Sin embargo si quisiéramos agregar un segundo botón, el diseñador marcaría un error ya que el elemento Window no está preparado para poder posicionar dos controles diferentes a ese mismo nivel.

 

Imagen 1. Error en el diseñador de Visual Studio 2008

  

El control Grid como mencionamos anteriormente nos permitirá organizar y desplegar nuestros controles pero en formato de cuadricula (Filas y columnas). La tabla 1 muestra los principales elementos del control Grid

 

Elemento

Descripción

ColumDefinition

Permite definir las diferentes columnas que contendrá el grid, asi como las propiedades de cada columna, alto, ancho etc.

RowDefinition

Cada elemento RowDefinition creado, especifica una fila dentro del Grid, también permite especificar el comportamiento de cada fila como, el tamaño máximo, tamaño mínimo etc.

   

Tabla 1. Principales elementos del control Grid

  

Elemento

Descripción

ShowGridLines

Indica si las líneas del grid serán mostradas, de manera predeterminada es false.

BackGround

Especifica un color de fondo

   
 

Tabla 2. Principales propiedades del control Grid

 

En el siguiente ejemplo, crearemos un control Grid que contenga 2 columnas de 150 pixeles de ancho cada una  y 12 filas, el grid mostrara las líneas de división así como un color de fondo blanco.

<Window x:Class="Users_SimpleControls.Window1"
 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 
    Title="Users_SimpleControls" Height="400" Width="300"
 
    >
 
     <Grid ShowGridLines="True" Background="White">
 
          <Grid.ColumnDefinitions>
 
                <ColumnDefinition Width="150"/>
 
                <ColumnDefinition Width="150"/>
 
          </Grid.ColumnDefinitions>
 
          <Grid.RowDefinitions>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
                <RowDefinition/>
 
          </Grid.RowDefinitions>
 
  
     </Grid>
 
</Window>
 

 

    Con las creación de las filas y columnas especificamos el layout que deberá de cumplir nuestra ventana que estamos diseñando, lo que haremos a continuación será indicarle a los controles en qué posición de nuestro grid serán ubicados, es decir en que fila y columna serán desplegados, todos los controles cuentan que la propiedad Grid.Colum y Grid.Row que indican en que columna y que fila será posicionado el control. Partiendo del ejemplo anterior, crearemos un elemento Label (el control será explicando más adelante) el cual será posicionado en la columna 0 fila 2 

<Label Grid.Column="0" Grid.Row="2">Apellido Materno</Label>  

 

Imagen 2. Control Label posicionado dentro del grid

 

El control Grid podría ser el control más utilizado al momento de realizar el LayOut de nuestra ventana ya que permite posicionar los controles como si se tratara de una tabla

 

Si no se especifica ningún valor de dimensión (Height o Width) en el control de Grid ni en su elemento Grid.ColumnDefinitions entonces el control ocupara el 100% del  tamaño de la ventana. En caso de las dimensiones de la ventana sean actualizadas entonces de  manera automática el control Grid reajustara su tamaño para adaptarse de manera automática al nuevo tamaño

 

Label

El control label  permite desplegar texto y posicionarlo en la región que especifiquemos para ello. Las principales propiedades son descritas en la tabla 3

 

Propiedad

Descripción

Content

Asigna el texto que será mostrado dentro del control

Background

Especifica un color de fondo

Label.BorderThickness

Asigna el ancho del borde de la etiqueta

BorderBrush

Especifica el tipo de brocha a utilizar para dibujar el borde

Height

Especifica el alto de la etiqueta

Width

Asigna el ancho de la etiqueta

 

Tabla 3. Principales propiedades del control Label

 

En el siguiente ejemplo crearemos una etiqueta que desplegara el texto “Apellido Materno” y le especificaremos un borde de 2 puntos de ancho de  color rojo

<Label Grid.Column="0" Grid.Row="2" Content="Apellido Materno" BorderBrush="Red">                
                    <Label.BorderThickness>2</Label.BorderThickness>                   
 
         </Label>
 

Imagen 3. Label con las propiedades configuradas

 

TexBox

Permite la captura de información en texto plano por parte del usuario, las principales propiedades son descritas en la tabla 4

 

Propiedad

Descripción

Content

Asigna u obtiene el texto  mostrado dentro del control

Background

Especifica un color de fondo

SpellCheck.IsEnabled

Permite la comprobación de errores gramaticales dentro del control

ContextMenu

Asigna un menú contextual personalizado

Height

Especifica el alto de la etiqueta

Width

Asigna el ancho de la etiqueta

 

Tabla 4. Principales propiedades del control TextBox

En el siguiente ejemplo se crea un control Texbox con un color de fondo “Azure” el texto “Casador” y con la comprobación gramatical activada

<TextBox Grid.Column="1" Grid.Row="2" SpellCheck.IsEnabled="True" Background="Azure">Casador</TextBox>
 

 

 En la siguiente imagen muestra como el corrector gramatical marca con una línea en rojo la palabra “Casador” al dar un clic con el botón derecho, se muestra un menú contextual sugiriendo la palabra correcta “Cazador” 

 

Imagen 4. Texbox con la comprobación gramatical activada

 

ComboBox

Permite desplegar información en forma de lista seleccionable, cada uno de estos elementos tiene  un nombre asignado el cual permite conocer cuál es el valor que el usuario ha seleccionado.

 

En el siguiente ejemplo, crearemos un ComboBox con el nombre “cboRangoEdad” que contendrá 3 elementos del tipo ComboBoxItem, cada uno de ellos corresponde a un rango de edad, al  último elemento se le asignara un color de fondo verde.

<ComboBox Grid.Column="1" Grid.Row="3" Name="cboRangoEdad">
 
                <ComboBoxItem  Name="Rango1">18 a 30 años</ComboBoxItem>
 
                <ComboBoxItem  Name="Rango2">31 a 50 años</ComboBoxItem>
 
                <ComboBoxItem  Name="Rango3" Background="Green">50 en adelante</ComboBoxItem>
 
          </ComboBox> 
 

 

En tiempo de diseño, nos asociaremos al evento “SelectionChanged” el cual se ejecutara cuando el usuario seleccione un elemento dentro del combobox. Primero, crearemos el código que se ejecutara cuando el usuario seleccione un elemento 

void cboRangoEdad_SelectionChanged(object sender, SelectionChangedEventArgs e)
 
      {
 
          ComboBoxItem elementoSeleccionado = cboRangoEdad.SelectedItem as ComboBoxItem;
 
          string mensaje = string.Format("El valor seleccionado es '{0}' con el texto '{1}'",elementoSeleccionado.Name,elementoSeleccionado.Content);
 
          MessageBox.Show(mensaje);
 
      }
 
  El código anterior, mostrara un mensaje con el nombre y el valor del elemento seleccionado, la propiedad “SelectItem” es del tipo object por lo cual es necesario convertirlo al tipo ComboBoxItem y de esa manera, obtener la información de dicho objeto. Lo único que hace falta, es asociar la función “cboRangoEdad_SelectionChanged” con el evento  “SelectionChanged” 
<ComboBox Grid.Column="1" Grid.Row="3" Name="cboRangoEdad" SelectionChanged="cboRangoEdad_SelectionChanged">
 

Imagen 5. Aplicación en ejecución, dar un clic sobre el ComboBox para desplegar la información

 

Imagen 6. Cuando se selecciona un elemento, el evento SelectionChanged es lanzado.

 

RadioButton

 

El control RadioButton permite al usuario seleccionar un valor de manera excluyente dentro de un grupo de elementos, es decir, solo permite la selección de un valor dentro de un determinado grupo. El ComboBox y el RadioButton comparten el mismo objetivo, sin embargo, el primero se presenta como una lista desplegable y el segundo se muestra con el comportamiento de un botón, con lo cual se logra una experiencia de usuario diferente.

 

En el siguiente ejemplo crearemos dos controles del tipo RadioButton los cuales estarán asociados utilizando la propiedad “GroupName”, si el nombre del grupo no es establecido o el nombre del grupo es diferente entonces los controles no quedarían asociados permitiendo al usuario seleccionar ambos controles a la vez.

 

El corrector de ortografía es soportado en los controles TextBox y RichTextBox

 

El control ComboBox permite crear sus elementos a partir la información almacenada en la base de datos, para mayor referencia puede buscar la utilización de las propiedades ItemsSource, DataContext, DisplayMemberPath y SelectedValuePath

<RadioButton Grid.Column="1" Grid.Row="4"  Name="rdEstadoCivilSoltero" GroupName="EstadoCivil">Soltero</RadioButton>
 
     <RadioButton Grid.Column="1" Grid.Row="5"  Name="rdEstadoCivilCasado" GroupName="EstadoCivil">Casado</RadioButton>   
 

En caso de que necesitemos conocer cuál fue el control radiobutton que selecciono el usuario podemos asociarnos al evento “Checked” el cual es ejecutado en el momento en que el usuario selecciona un valor, para implementarlo podernos realizar el siguiente procedimiento.

 Crearemos una función que será llamada por ambos radiobuttons (rdEstadoCivilSoltero y rdEstadoCivilCasado), está función recibe como parámetro el sender, el cual, es el objeto que fue seleccionado, como es del tipo object es necesario convertirlo al tipo RadioButton para poder acceder a su información 

void EstadoCivilSeleccionado(object sender, RoutedEventArgs e)        
{            
    RadioButton objetoSeleccionado = sender as RadioButton;           
     MessageBox.Show(" El valor seleccionado fue " + objetoSeleccionado.Content);        
} 

El siguiente paso, será asociar la función “EstadoCivilSeleccionado” al evento “Checked” de ambos controles

<RadioButton Grid.Column="1" Grid.Row="4"  Name="rdEstadoCivilSoltero" GroupName="EstadoCivil" Checked="EstadoCivilSeleccionado">Soltero</RadioButton>     <RadioButton Grid.Column="1" Grid.Row="5"  Name="rdEstadoCivilCasado" GroupName="EstadoCivil" Checked="EstadoCivilSeleccionado">Casado</RadioButton>  

 

Imagen 8. Cuando un valor es seleccionado, se mostrara un mensaje con la información del mismo.

 

Image

El control image permite visualizar imágenes que se encuentren en cualquiera de los siguientes formatos:

·         BMP

·         JPEG

·         PNG

·         TIFF

·         Windows Media Photo

·         GIF

·         ICON

 

Las principales propiedades son descritas en la tabla 5

 

Propiedad

Descripción

Source

Especifica la ruta en donde se encuentra la imagen a desplegar, incluso podría utilizarse una dirección de internet que contiene la url de la imagen a desplegar

Height

Especifica el alto de la imagen

Width

Asigna el ancho de la imagen

 

Tabla 5. Principales propiedades del control Image

 

En el siguiente ejemplo  mostraremos una imagen gif que tiene transparencia.

<Label Grid.Column="0" Grid.Row="6"  >Imagen</Label>        
       <Image  Grid.Column="1" Grid.Row="6" Source="logoMS.gif" Width="300" Height="35"/>

 

 

Imagen 9. La imagen es visualizada sin embargo, solo los bordes son visualizados ya que la mayoría del cuerpo de la imagen tiene aplicada transparencia

 

Para que la imagen sea visualizada de manera correcta es necesario aplicar un color de fondo, para ello utilizaremos un control de tipo Canvas al cual le aplicaremos un color de fondo azul y por ultimo agregaremos el control Image como un control hijo del control canvas.

<Label Grid.Column="0" Grid.Row="6"  >Imagen</Label>        
       <Image  Grid.Column="1" Grid.Row="6" Source="logoMS.gif" Width="300" Height="35"/>

 

 Articulo Publicado en http://desarrollador.redusers.com/