Manual
Manual
Foundation 4.0
Visual Studio 2010
Alhambra-eidos
08/02/2011
Windows Workflow Foundation 4.0 2011
TABLA DE CONTENIDOS
INTRODUCCIÓN ............................................................................................................................. 4
CONCEPTOS PREVIOS ................................................................................................................ 6
ARQUITECTURA DE WINDOWS WORKFLOW 4.0 ...................................................................... 7
ACTIVIDADES ................................................................................................................................. 9
Ejemplo- Hola Mundo ............................................................................................................. 10
Actualizar el método Main para usar el nuevo nombre ..................................................... 13
La Actividad CodeActivity ........................................................................................................ 14
FLUJOS DINÁMICOS CON XAML .................................................................................................. 16
PROBAR LOS FLUJOS DE TRABAJO .............................................................................................. 19
Crear una prueba unitaria ....................................................................................................... 19
WORKFLOWAPPLICATION ........................................................................................................... 24
Devolver el Flujodetrabajo como un argumento .................................................................... 25
Modificar la prueba para utilizar WorkflowApplication.......................................................... 28
Delegados, no eventos ........................................................................................................ 29
Verificar el resultado ........................................................................................................... 29
Lógica If/Else ............................................................................................................................... 31
Manejo de Errores....................................................................................................................... 35
Añadir la actividad try/Catch al flujo de trabajo ..................................................................... 35
ACTIVIDADES PERSONALIZADAS ................................................................................................. 39
Crear una actividad básica ...................................................................................................... 39
Propiedades de dependencia .................................................................................................. 40
Creación de actividades compuestas ...................................................................................... 43
Actividades asíncronas y basadas en eventos......................................................................... 46
Control de errores ................................................................................................................... 48
Experiencia de diseño ............................................................................................................. 49
Validación ................................................................................................................................ 52
DISEÑADORES ALOJADOS............................................................................................................ 54
EJEMPLOS .................................................................................................................................... 58
Para crear la actividad ReadInt ............................................................................................... 58
Para crear la actividad Prompt ................................................................................................ 59
Para crear el proyecto de flujo de trabajo .............................................................................. 60
2
Windows Workflow Foundation 4.0 2011
3
Windows Workflow Foundation 4.0 2011
INTRODUCCIÓN
Un flujo de trabajo es un conjunto de unidades elementales llamadas actividades que están
almacenadas como un modelo que describe un proceso real. Los flujos de trabajo proporcionan
una manera de describir el orden de ejecución y las relaciones de dependencia entre las partes de
trabajo de ejecución tanto corta o prolongada. Este trabajo pasa a través del modelo desde un
principio hasta un final y las actividades pueden ser ejecutadas por personas o por funciones de
sistema.
Las instancias de flujo de trabajo en ejecución se crean y se mantienen por medio de un motor
de tiempo de ejecución con el que el proceso de host interactúa a través de alguna de las
siguientes clases:
4
Windows Workflow Foundation 4.0 2011
4
2
2. Antes de invocar una nueva instancia de flujo de trabajo no es necesario esperar a que se
complete la instancia de flujo de trabajo en ejecución. El motor de tiempo de ejecución
permite ejecutar varias instancias de flujo de trabajo simultáneamente. Los flujos de trabajo
invocados son los descritos a continuación:
Una actividad Sequence que contiene una actividad secundaria WriteLine. Las
actividades de tipo Sequence permiten añadir dentro diferentes actividades para
que estas se vean obligadas a ejecutarse de forma secuencial, en concreto, la
actividad WriteLine permite interactuar con la consola para escribir. Un objeto
Variable (más tarde lo veremos) de la actividad principal está vinculado a un
objeto InArgument de la actividad secundaria.
3. Una actividad personalizada llamada ReadLine, esta actividad permite leer de consola. Un
argumento OutArgument de la actividad ReadLine se devuelve al método Invoke de
llamada.
5
Windows Workflow Foundation 4.0 2011
Antes de continuar, repasemos, lo visto. Lo primero que necesitamos para iniciar un flujo de
trabajo es el método Invoke, en cuanto se inicia el flujo de trabajo, en este caso concreto una
actividad de tipo secuencia, que as u vez ésta compuesta por varias actividades que son el
escribir en la consola el valor de una variable. Pero resulta que podemos iniciar varios flujos de
trabajo, en este caso un segundo con una actividad de tipo ReadLine que permite leer de
consola.
CONCEPTOS PREVIOS
Dado que los pasos del flujo de trabajo se definen como una jerarquía de actividades, se
puede decir que la actividad de nivel superior en la jerarquía define el propio flujo de
trabajo.
Bien, teniendo esto en cuenta. ¿Cómo se comunican las actividades? ¿Cómo pueden compartir
información de cada actividad? ¿Cómo se almacenan las actividades? Las actividades se
almacenan y comparten datos entre ellas a través de los siguientes tipos:
6
Windows Workflow Foundation 4.0 2011
Las actividades se desarrollan como tipos CLR que derivan de Activity, CodeActivity o
NativeActivity, o sus variantes que devuelven un valor, Activity, CodeActivity o
NativeActivity. Desarrollar actividades que derivan de Activity le permite al usuario ensamblar
objetos WorkflowElement existentes previamente para crear las unidades de trabajo que se
ejecutan en el entorno del flujo de trabajo.
CodeActivity, por otro lado, permite crear la lógica de ejecución en código administrado
usando principalmente CodeActivityContext para el acceso a los argumentos de actividad.
Desarrollar actividades que derivan de NativeActivity permite a los usuarios tener acceso al
tiempo de ejecución a través de ActivityExecutionContext para funciones como la
programación de elementos secundarios, la creación de marcadores, invocar el trabajo
asincrónico, el registro de transacciones y mucho más.
La creación de actividades que derivan de Activity son declarativas. Estas actividades se pueden
crear en XAML.
Una vez llegado este punto, cambia al estado Cerrado. El elemento primario de una instancia de
actividad puede pedir a un elemento secundario que cancele; si el elemento secundario puede
cancelarse, se completa en el estado Cancelado.
7
Windows Workflow Foundation 4.0 2011
8
Windows Workflow Foundation 4.0 2011
ACTIVIDADES
Las actividades representan bloques de compilación mínimos para los flujos de trabajo. La clase
Activity es la clase base para todas las actividades posibles.
Activity define un conjunto de propiedades y eventos, como cualquier clase, junto con la lógica
de ejecución que define el comportamiento del tiempo de ejecución de la actividad. Se puede
asociar a una Activity un conjunto de componentes adicionales a. Estos incluyen, pero sin
limitarse a, un validador, un generador de código, serializadores personalizados y un diseñador.
Todas las actividades comparten un conjunto común de propiedades definido en la clase base
Activity. Cada Activity puede declarar sus propias propiedades adicionales según sus
necesidades extendiendo esta clase. Dado que Activity deriva de DependencyObject, las
propiedades se pueden definir como propiedades CLR estándar y como propiedades de
dependencia.
La lógica de ejecución de Activity cumple un contrato que existe entre Activity y el tiempo de
ejecución del flujo de trabajo. Usted debe documentar la lógica de ejecución de Activity en un
sentido funcional, para que un programador del flujo de trabajo que utiliza Activity conozca
cómo se comporta. La propia lógica de ejecución se oculta del programador del flujo de trabajo
que incluye la actividad en un flujo de trabajo, porque la lógica de ejecución forma parte de un
contrato que existe estrictamente entre el flujo de trabajo en tiempo de ejecución y Activity.
En el siguiente ejemplo se define una actividad cuyo propósito es enviar un correo electrónico.
La actividad define una propiedad, Subject, que usa una propiedad de dependencia en su
implementación. Se pueden definir otras propiedades de una manera similar. El método Execute
se invalida para proporcionar la lógica para enviar el correo electrónico.
9
Windows Workflow Foundation 4.0 2011
Ya se ha comentado anteriormente que los flujos de trabajo son una manera de ejecutar procesos
de negocio. Veamos un ejemplo sencillo paso a paso e como implementar una actividad:
En este ejemplo se creará un flujo muy simple que será básicamente lo equivalente al siguiente
código:
1. Iniciar Visual Studio 2010 desde Inicio | Todos los programas | Microsoft Visual Studio
2010.
10
Windows Workflow Foundation 4.0 2011
Ya estaría el flujo de trabajo. La actividad WriteLine es una actividad simple que mostrará un
mensaje en la consola. La propiedad Text es una expresión que podría resultar de llamar a una
función o evaluar la propiedad de un objeto. En este caso, la expresión es un literal string por lo
debemos entrecomillar el string.
Imaginemos que una vez que hemos implementado nuestro flujo de trabajo decidimos
refactorizarlo. A pesar de que tengas una aplicación trabajando, quizá quieras llevar a cabo
algunas mejoras. Veamos a través del ejemplo anterior como hacerlo.
Para este caso concreto, se especifico como Workflow1 el cual no es muy descriptivo,
cambiaremos el nombre del flujo de trabajo a HolaMundo y veremos como el cambio de
nombre afecta al resto del programa.
11
Windows Workflow Foundation 4.0 2011
Para cambiar el nombre del flujo de trabajo definido en Workflow1.Xaml, Abrirlo con el
diseñador de flujos de trabajo y hacer clic en un área vacía del área de diseñador. Esto permite
cambiar las propiedades del flujo de trabajo.
Clic Aquí
Mientras no se necesite, es buena idea para el nombre del archivo xaml hacer que coincida con
el nombre de la actividad contenida en el. En el explorador de soluciones, podemos de igual
manera hacer clic con el botón derecho en el xaml y selecciona la opción renombrar para que
coincida.
Nota: tener cuidado cuando se renombran archivos xaml por que a diferencia de los archivos
que contienen clases, en estos no se renombran de forma automática el nombre de la clase
asociada sino que hay que hacerlo de forma manual.
12
Windows Workflow Foundation 4.0 2011
¿Por qué falla la aplicación al compilar cuando cambiamos el nombre de un flujo de trabajo?
Windows Workflow Foundation 4.0 ejecuta un flujo de trabajo con el Workflow Runtime. La
manera más fácil de invocar el runtime es usando la clase WorkflowInvoker la cual es la que la
plantilla de aplicación de consola de flujo de trabajo usa.
class Program
{
static void Main(string[] args)
{
WorkflowInvoker.Invoke(new HolaMundo());
}
}
¿Por qué Visual Studio me informa de que el tipo HolaMundo no está definido? Si cambias el
Main() después de compilar el flujo de trabajo con el nombre HolaMundo, se mostrará una
advertencia acerca del tipo HolaMundo de que no está definida. La razón es que Visual Studio
no es consciente de los tipos declarados en XAML hasta que se genera el ensamblado.
Ejecutamos la aplicación para comprobar que las modificaciones realizadas, dejan la aplicación
en un estado correcto:
13
Windows Workflow Foundation 4.0 2011
La Actividad CodeActivity
Como hemos comprobado en el ejemplo anterior Windows Workflow Foundation 4.0 consiste
en un diseñador que edita archivos .xamls y un runtime que invoca actividades. Al crear un flujo
de trabajo, creamos un nuevo tipo de actividad y debido a que las actividades son justamente
clases que heredan de System.Activities.Activity o una de sus subclases, puedes declarar flujos
de trabajo usando C#, VB o XAML.
CodeActivity es una clase abstracta que se usa para crear una actividad personalizada con
comportamiento imperativo definido con el método Execute(CodeActivityContext), que da
acceso a la resolución de variables, argumentos y extensiones.
public ActividadHolaMundo() {
}}
Este enfoque es útil si estas creando un flujo de trabajo fuera de otras actividades que realizan el
trabajo como en el ejemplo anterior con la actividad WriteLine. Sin embargo, a veces cuando
creamos una actividad implementamos la lógica de negocio en si misma o mediante la llamada a
otra clase que no es una actividad que hace el trabajo. Para hacer esto, heredaremos de una clase
base diferente System.Activities.CodeActivity y sobrescribiremos el método Execute.
1. Abrir Visual Studio 2010, desde Inicio | Todos los programas | Visual Studio 2010.
4. CodeActivity es una clase abstracta. Esto significa que cuando heredemos de ella,
deberíamos sobrescribir el método Execute. Esto es el lugar donde realizaremos el
trabajo de la actividad. Reemplazar la implementación predeterminada de la clase son el
siguiente código:
14
Windows Workflow Foundation 4.0 2011
WorkflowInvoker.Invoke(new HolaMundoEnCodigo());
Escribir la lógica de negocio en código no es nada nuevo. ¿Por qué hacer el esfuerzo de escribir
una clase especial que herede de CodeActivity? La razón es que hacer ahora la lógica de
negocio puede estar compuesta en otros procesos de negocio que usan el workflow runtime.
Como veremos más tarde también beneficia al modelo Multihilo y gestión de datos que
proporcionan una alta escalabilidad.
15
Windows Workflow Foundation 4.0 2011
A pesar de que podría ser similar al formato de los archivos de origen no importa,. xaml ofrecen
algunas ventajas sobre creación de flujos de trabajo en C #.
El diseñador del flujo de trabajo trabaja con sólo con archivos .xaml, los flujos de
trabajo creados en C# no tienen soporte de diseño.
XAML puede ser cargado y ejecutado de forma dinámica sin compilarlo en el
ensamblado.
Los flujos de trabajo dinámicos proporcionan algunas posibilidades interesantes para los
programas que quieren generar lógicas de negocio o realizar decisión en tiempo de ejecución en
la que la lógica de negocio se carga y se ejecuta.
Anteriormente el flujo de trabajo era compilado en un tipo. Para invocar un flujo de trabajo
desde un archivo xaml necesitamos usar ActivityXamlService para cargar el archivo xaml en
16
Windows Workflow Foundation 4.0 2011
memoria y crear una instancia de una actividad que WorkflowInvoker puede invocar. Tener en
cuenta que cualquier ensamblado que al que se haga referencia en el archivo xaml debe estar
disponible cuando el flujo de trabajo este invocado.
using System.Activities.XamlIntegration;
17
Windows Workflow Foundation 4.0 2011
18
Windows Workflow Foundation 4.0 2011
Vamos a ver a continuación como modificar la aplicación HolaMundo para utilizar argumentos
y prepararla para ser útil en otros entonos que no sean los de la consola para devolver algún
saludo en vez de escribir directamente en la consola con la actividad WriteLine .
1. Para empezar a crear una prueba unitaria para el flujo de trabajo y verificar su
comportamiento, pulse con el botón derecho en el explorador de soluciones en la
solución Ejemplo1 y seleccione Añadir / Nuevo proyecto y establezca las opciones de
proyecto.
c. Nombre: FlujoHolaMundo.Test
19
Windows Workflow Foundation 4.0 2011
Una vez tenemos el entorno necesario para crear la prueba unitaria, vamos a crearla.
using System.Activities;
using Ejempo1;
2. Crear una prueba para asegurarse de que el flujo de trabajo se comporta como
queremos. Para hacer esto, abrir HolaMundoPrueba.cs, localizar el método method1 y
renombrarlo a DeberiaDevolverConNombre.
Puedes crear la actividad e inicializar los argumentos (los cuales son propiedades públicas)
usando la inicialización de objeto o pasando un diccionario de tipo Dictionary<string, object>
de parámetros de entrada que mapean los nombres de los argumentos de entrada de la actividad.
La interfaz para la actividad parece que está bien, pero veremos qué tal y como está ahora no
compila.
20
Windows Workflow Foundation 4.0 2011
6. Ejecutar la prueba
21
Windows Workflow Foundation 4.0 2011
1. Escribir texto en la consola con WriteLine no hace que pase la prueba por lo que
elimine la actividad WriteLine.
2. Necesita establecer el valor del argumento de salida Saludo, para hacer esto, arrastre
una actividad Assign del grupo primitivas en el cuadro de herramientas al área de
diseño.
22
Windows Workflow Foundation 4.0 2011
En el editor, puede escribir la expresión, incluyendo aquellas que usen líneas en VB. Establecer
la expresión a "Hola " + UserName + " desde Workflow 4":
23
Windows Workflow Foundation 4.0 2011
WORKFLOWAPPLICATION
Una vez llegados a este punto, hemos creado una actividad y la hemos invocado de la manera
más simple posible con la clase WorkflowInvoker. El método WorkflowInvoker.Invoke es
simple ya que es síncrono e invoca el flujo de trabajo en el mismo hilo que el llamante.
Otra manera de invocar un flujo de trabajo es con la clase WorkflowApplication. Esta clase
permite devolver un flujo de trabajo en un hilo aparte y suplir los delegados para ser invocado
cuando el flujo de trabajo se complete. Esto permite crear servidores Multihilo o programas
clientes Multihilo mucho más fácil que si no usáramos Windows workflow 4.0.
Devolver un entero distinto de cero conteniendo el ID del hilo gestionado del flujo de
trabajo que será invocado.
Usar el enfoque de “escribir primero la prueba”, empezará mediante la escritura de una prueba
que verifique el nuevo requisito del ID del hilo del flujo de trabajo.
using System.Threading;
using System.Diagnostics;
24
Windows Workflow Foundation 4.0 2011
Si ejecutamos el proyecto de prueba veremos que esta segunda prueba unitaria no se pasa.
Ahora que tenemos una prueba para verificar el comportamiento, necesitamos modificar el
flujo de trabajo para que pase la prueba.
25
Windows Workflow Foundation 4.0 2011
Hasta ahora, el flujo de trabajo ha sido solo una actividad. En este punto necesitamos dos
actividades, una para asignar el saludo y otra para asignar el hilo del flujo de trabajo.
Necesitamos para modificar el flujo de trabajo usar una actividad que contenga dos actividades
y hay varias actividades que podríamos elegir para hacerlo, pero empezaremos con la más
simple, con la actividad de secuencia.
26
Windows Workflow Foundation 4.0 2011
27
Windows Workflow Foundation 4.0 2011
Si queremos verificar el ID del hilo actual necesitamos usar WorkflowApplication para ejecutar
el flujo de trabajo. En el siguiente ejemplo modificaremos la prueba para capturar el hilo del
28
Windows Workflow Foundation 4.0 2011
sync.Set();
};
workflowApp.Run();
sync.WaitOne(TimeSpan.FromSeconds(1));
Assert.IsNotNull(output, "salida no establecida,
workflow ha tenido timed out");
Assert.IsTrue(output.ContainsKey("flujodetrabajo"),
"HolaMundo deberia contener un OutArgument llamado
flujodetrabajo");
var outarg = output["flujodetrabajo"];
Assert.IsInstanceOfType(outarg, typeof(Int32),
"flujodetrabajo deberia ser de tipo Int32");
Assert.AreEqual(actionThreadID, (int)outarg,
"flujodetrabajo deberia ser igual a actionThreadID");
Debug.WriteLine("Hilo Test es " +
Thread.CurrentThread.ManagedThreadId);
Debug.WriteLine("Hilo Workflow es " +
outarg.ToString());
}
Delegados, no eventos
Verificar el resultado
Ahora ya si estamos listos para comprobar si nuestra actividad pasa la prueba con los nuevos
requisitos.
29
Windows Workflow Foundation 4.0 2011
30
Windows Workflow Foundation 4.0 2011
Lógica If/Else
En el ejemplo anterior, creamos una aplicación de flujo de trabajo con un mensaje
personalizado. En este ejemplo, veremos cómo usar la lógica If/Else en el flujo de trabajo para
mostrar un mensaje diferente dependiendo de una condición personalizada.
Al igual que antes, primeramente escribiremos la prueba para el nuevo requisito. Si el nombre
tiene un número impar de letras la primera palabra será Saludos y sino Hola.
1. Crear una prueba unitaria que verifique el Nuevo requisito. Para ello añadir el siguiente
código al proyecto de prueba.
2. Clic en el botón Variables. Se mostrará un panel que mostrará a su ves todas las
variables disponibles para la actividad de secuencia.
31
Windows Workflow Foundation 4.0 2011
Como se observa, aparece en la actividad el icono de Warning lo que nos indica que la actividad
no es válida. La actividad If está todavía sin especificar una condición.
6. Modificar una expresión por la condición if. Para hacer esto, doble clic en la actividad
If para abrirla y escribir la siguiente expresión en el cuadro condición. Comprobará el
nombre si es impar o no.
32
Windows Workflow Foundation 4.0 2011
Las expresiones son sentencias programadas que puedes ser literales, o sentencias condicionales
una expresión que concatene varios strings o llamas a métodos o invocar otra actividad. Las
expresiones son escritas mediante la sintaxis de Visual Basic incluso si la aplicación está en C#.
Esto significa que la capacitación no importa, la comparación es realizada usando un símbolo
equals en vez de “==”, y los operadores booleanos son la palabras “And” y “Or”.
7. Actualizar el valor de la variable FirstWord , la cual debería ser “Hola”. Arrastrar una
actividad Assign desde el grupo primitivas en el cuadro de herramientas en el área del
Then. Después, escribir FirstWord en el cuadro To y “Saludos” en el valor.
33
Windows Workflow Foundation 4.0 2011
9. Ya sólo queda verificar el correcto comportamiento del flujo de trabajo, para ello
ejecutamos la prueba.
34
Windows Workflow Foundation 4.0 2011
Manejo de Errores
Puede haber notado un error potencial en la aplicación y eso que es muy sencilla. ¿Qué sucede
si no pasamos un nombre de usuario para el flujo de trabajo? En el siguiente ejemplo, agregará
un control de errores para el flujo de trabajo utilizando el Try / Catch, <T> .
Destacar que si pasamos un string vacio la aplicación debería funcionar correctamente. La única
manera de obtener null en el nombre pasado en el flujo de trabajo es para crearlo sin
suministrarlo en el argumento UserName.
Para hacer esto, añadir un nuevo método como prueba unitaria, como se muestra a continuación:
HelloWorkflow.Tests.SayHelloFixture.ShouldHandleNullUserName threw
exception: System.NullReferenceException: Object reference not set to
an instance of an object
Para manejar el error, podríamos validar el argumento nombre antes de usarlo o simplemente
podríamos capturar la excepción y tratarla.
35
Windows Workflow Foundation 4.0 2011
La actividad Try/Catch puede ser usada por flujos de trabajo para manejar excepciones
que son lanzadas durante la ejecución de un flujo de trabajo. Estas excepciones pueden
ser manejadas o propagadas usando la actividad Throw. Las actividades en la sección
Finally son ejecutadas cuando incluso la sección try se completa o se entra en la sección
Catch.
36
Windows Workflow Foundation 4.0 2011
37
Windows Workflow Foundation 4.0 2011
6. Ahora necesitamos fijar la prueba para que espere ésta excepción. Para hacer esto, abrir
HolaMundo.cs y añadir la anotación ExceptedException en el método que funciona
como prueba unitaria como se muestra a continuación.
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldHandleNullUserName()
{
// Invocar sin argumentos WorkflowInvoker.Invoke(new HolaMundo());
}
38
Windows Workflow Foundation 4.0 2011
ACTIVIDADES PERSONALIZADAS
Las actividades personalizadas de los flujos de trabajo constituyen uno de los aspectos más
importantes de Windows Workflow Foundation, por lo que se deben tener en cuenta varias
características a la hora de crearlas. Vamos a ver los componentes básicos necesarios para crear
actividades personalizadas para el dominio empresarial, entre otras las responsabilidades en
tiempo de ejecución, la experiencia en tiempo de diseño o el desarrollo de actividades
asincrónicas.
Al crear una actividad personalizada, la primera decisión que se debe tomar consiste en optar
por una actividad simple o compuesta. Las actividades simples, o básicas si se prefiere, son
aquéllas cuya lógica y ejecución se encuentran encapsuladas en el propio código de la actividad.
Son actividades simples, por ejemplo, la actividad SendEmail del SDK de Windows o una
actividad que permita consultar datos de una base de datos.
Las actividades reutilizables, por ejemplo, las de aprobación del administrador, constan de
varios pasos de fácil modelado con una recopilación de actividades existentes. La actividad de
aprobación del administrador puede servirse de actividades como IfElse con el fin de determinar
si el administrador se encuentra en línea. En caso afirmativo, se le podría enviar un mensaje
instantáneo; de lo contrario, bastaría con enviar un mensaje de correo electrónico. Esta actividad
encapsula toda la compleja lógica de una solicitud de aprobación, la cual forma parte de un flujo
de trabajo y constituye en sí misma un flujo.
El mero hecho de incluir esta actividad compuesta en sus flujos de trabajo libra a los usuarios de
esta actividad de tener que hacerse cargo de las complejidades y los detalles de ponerse en
contacto con el administrador.
En muchos aspectos, crear una actividad es parecido a crear un componente. Al fin y al cabo,
una actividad es un componente reutilizable que aprovecha las características de Windows
Workflow Foundation, el marco en el que se ejecuta. Así pues, el primer paso para crear una
actividad consiste en determinar su función y su interfaz. En el caso de este ejemplo es crear la
actividad CreateUser, la función es crear un usuario mediante el modelo de proveedores de
suscripciones de ASP.NET. Por consiguiente, la interfaz requerirá las propiedades necesarias
para crear un usuario: dirección de correo electrónico, nombre de usuario, contraseña y otros
datos similares.
39
Windows Workflow Foundation 4.0 2011
El código que controla la función de una actividad básica se escribe en el método Execute
sustituido de la clase base Activity. Aparte del código específico de la función de la actividad, el
desarrollador también tiene la responsabilidad de devolver el estado de la actividad. En el caso
de las actividades básicas, casi siempre será el estado Closed. Al devolver Closed, se indica al
tiempo de ejecución del flujo de trabajo que la actividad finalizó su ejecución, por lo que es
libre de programar la siguiente actividad del flujo de trabajo.
En la siguiente imagen se muestra una actividad básica empleada para crear un usuario del
sistema de suscripciones de ASP.NET.
MembershipCreateStatus status;
mp.CreateUser(UserName, Password, Email, null, null, true,
Guid.NewGuid(), out status);
return ActivityExecutionStatus.Closed;
}
Propiedades de dependencia
40
Windows Workflow Foundation 4.0 2011
Ahora bien, imaginemos que desea contar con un mecanismo que permita crear flujos de trabajo
a personal no especializado. No conviene que todos los usuarios tengan que escribir código sólo
para conectar los datos de una actividad a otra. Gracias al modelo declarativo de Windows
Workflow Foundation, es más fácil actuar en esta situación, y una de las características que
sustenta este modelo son las propiedades de dependencia.
Las propiedades de dependencia son un medio para almacenar los valores de una actividad o del
estado de un flujo de trabajo. A diferencia de las propiedades estándar en las que el valor se
almacena dentro de la propia clase, el valor de las propiedades de dependencia se almacena en
un diccionario de cuyo mantenimiento se ocupa la clase base DependencyObject.
Este tipo de enlace traslada al campo de los componentes el mismo modelo eficaz del que
depende una gran mayoría de desarrolladores de interfaces de usuario. El enlace de actividades
simplifica en gran medida la conexión de componentes. Además, confiere plausibilidad a la idea
de que quienes no sean programadores sean capaces de crear flujos de trabajo. Si las actividades
cuentan con un diseño adecuado, los usuarios han de poder arrastrarlas a una superficie de
diseño con objeto de conectar los valores entre ellas sin necesidad de escribir código.
41
Windows Workflow Foundation 4.0 2011
El segundo paso consiste en definir una propiedad estándar de .NET con métodos get y set; en
este caso, se confía en la clase base para almacenar o recuperar el valor de la propiedad de
dependencia. Recuerde que existe un fragmento de código para Visual Studio® 2005 que
facilita este proceso. El código que hay a continuación muestra la propiedad UserName
redefinida como propiedad de dependencia.
Una pregunta que se suele plantear es cuándo debe usar el desarrollador propiedades de
dependencia en lugar de propiedades estándar de .NET. La respuesta es muy sencilla: las
propiedades de dependencia se deben emplear en cualquier propiedad que se beneficie de estar
enlazada a otra propiedad u otro campo. Lo cierto es que no se puede esgrimir ningún
argumento bueno para no usar las propiedades de dependencia, y menos con lo fáciles que son
de escribir gracias a los fragmentos de código disponibles.
42
Windows Workflow Foundation 4.0 2011
Aunque las actividades básicas aportan un gran valor, con frecuencia es más conveniente
suministrar componentes reutilizables de mayor complejidad. Uno de esos tipos de
componentes es la actividad reutilizable que incluye varias actividades básicas para representar
una interacción reutilizable o un flujo de lógica; por ejemplo, sería una actividad compuesta la
que, en primer lugar, solicite la aprobación de un administrador antes de crear un usuario. En
esta actividad única estarían contenidas la solicitud de permiso, la recepción de la respuesta y,
por último, la creación del usuario. El objetivo a la hora de crear esta actividad compuesta ha de
ser facilitar que el usuario la agregue a un flujo de trabajo sin tener que preocuparse por las
complejidades inherentes al proceso de aprobación ni por su funcionamiento.
Este tipo simple de actividad compuesta reutiliza el control de ejecución de una clase base
existente, a menudo la clase SequenceActivity. Se trata de una situación tan habitual que Visual
Studio Extensions para Windows Workflow Foundation incorpora un diseñador visual idóneo
para este tipo de actividad. Basta con agregar una actividad nueva al proyecto en marcha para
disponer del punto de partida de una actividad compuesta derivada de la actividad Sequence y
de la capacidad precisa para definir los pasos del componente reutilizable del mismo modo que
se define un flujo de trabajo. Gracias al explorador de propiedades, se puede cambiar la clase
base a cualquier otra actividad compuesta a fin de alterar la semántica de la ejecución sin dejar
de usar el diseñador para crear la lógica de la actividad. En la siguiente imagen se muestra el
diseñador de actividades que se emplea para crear una actividad compuesta a partir de la
actividad Sequence.
Al encapsular actividades, surge la necesidad de exponer las propiedades de las actividades incluidas
ante los usuarios de la actividad compuesta. En el ejemplo anterior, el usuario de la actividad
compuesta debe ser capaz de suministrar valores para el nombre de usuario, la dirección de correo
electrónico, las funciones y otros datos precisos para la correcta configuración de las actividades
incluidas. Visual Studio Extensions hace que resulte sencillo gracias al mecanismo denominado
promoción de propiedades. En el diseñador de actividades compuestas, al hacer clic con el botón
secundario en una actividad, emerge un menú contextual con una opción que permite promover las
propiedades susceptibles de enlace de la actividad. Si elige esa opción, se declaran las propiedades
de dependencia en la actividad compuesta y se enlazan las propiedades de la actividad incluida a
43
Windows Workflow Foundation 4.0 2011
dichos valores. Con este procedimiento, se exponen las propiedades que se deben establecer sin que
sea necesario escribir el código que conecta los valores. Puede determinar cómo se llamará la
propiedad expuesta para los usuarios mientras mantiene ocultos los detalles de implementación de
la actividad.
En caso de que desee ejercer un mayor control sobre la ejecución de las actividades secundarias,
puede escribir una actividad derivada de CompositeActivity y, en el método Execute, controlar la
programación de dicha ejecución. Consideremos, por ejemplo, la actividad Switch. La actividad IfElse
disponible como parte de .NET Framework 3.0 proporciona el modelo para ejecutar con condiciones
una única rama de actividades. La actividad Parallel ofrece un modelo de ejecución de todas las
ramas. Sólo la actividad ConditionedActivityGroup (CAG) aporta un modelo de ejecución condicional
de varias ramas. Switch es más sencilla que CAG y, además, supone un mecanismo adecuado para
mostrar cómo se controla la ejecución de las actividades secundarias para posibilitar la ejecución
condicional de varias ramas de actividades en función de decisiones de código o reglas.
En la siguiente imagen se ilustra el empleo de la actividad Switch en un flujo de trabajo. Fíjese en que
cada una de las ramas de la actividad cuenta con una propiedad denominada Condition que se
puede establecer en una condición de regla declarativa o una condición de código de la misma
forma que las condiciones de una rama de una actividad IfElse. Sólo cuando hay presente una
condición y ésta se evalúa en True, se ejecuta esa rama de la actividad
44
Windows Workflow Foundation 4.0 2011
Es probable que cada actividad compuesta aplique una semántica distinta al modo de ejecutar
las actividades secundarias en función de las necesidades del creador y del caso concretos. El
ejemplo pretende ofrecer una visión general de los asuntos principales que preocupan a los
desarrolladores cuando crean actividades compuestas.
45
Windows Workflow Foundation 4.0 2011
Si bien algunas actividades pueden finalizar su trabajo de una forma sincrónica simple, existen
numerosos casos en los que la actividad inicia alguna tarea y, luego, queda a la espera de una
respuesta. De igual modo, es posible que deba crear una actividad capaz de escuchar si se
provoca algún evento externo como, por ejemplo, la creación de un archivo o un evento del
Instrumental de administración de Windows (WMI). Dada la manera en que se administran los
flujos de trabajo en tiempo de ejecución, no conviene crear directamente en las actividades
controladores de eventos para los recursos externos. Por ejemplo, supongamos que se registra
un controlador de eventos en la actividad relativo a los cambios producidos en el sistema de
archivos. Si el flujo de trabajo entra en un estado inactivo serializado, el controlador también
acabaría en estado de inactividad. Entonces los eventos provocados no llegarían a conocimiento
de la actividad.
Windows Workflow Foundation ofrece una infraestructura que ayuda a paliar este problema de
comunicación con los flujos de trabajo que se mantiene en la actualidad. El modelo de
comunicación se basa en un sistema de colas: por lo general, las actividades se registran para
recibir mensajes en una cola y los servicios de la aplicación host envían mensajes a colas. Las
actividades personalizadas pueden valerse de este modelo tanto para controlar los eventos
externos como para comunicar la finalización de la ejecución de actividades asincrónicas. Así la
actividad se puede ejecutar hasta un punto determinado y, a continuación, esperar un estímulo
para continuar la ejecución. En la siguiente imagen se representa el modelo de comunicación
entre el código de la aplicación host y el código o las actividades del flujo de trabajo.
Con objeto de permitir que la actividad escuche los mensajes que llegan a una cola, es preciso
asegurarse primero de que dicha cola exista. En caso de que no exista, hay que crearla. Esto se
suele llevar a cabo en los métodos Initialize o Execute de la actividad según el momento en que
la cola deba estar disponible para recibir mensajes. WorkflowQueuingService proporciona los
métodos necesarios para crear, buscar o eliminar colas de flujos de trabajo. Por último, la
actividad se debe registrar para recibir estas notificaciones efectuando el registro para el evento
QueueItemAvailable en la propia cola del flujo de trabajo. En cuanto compruebe la existencia
de la cola y se registre para recibir eventos, se enviará una notificación a la actividad siempre
que haya elementos disponibles en la cola para que se puedan obtener y procesar.
Cuando crea una actividad asincrónica, sigue los pasos que acabo de describir con el fin de
preparar la actividad para la recepción de mensajes de la cola; una vez finalizada la actividad
asincrónica, pone en cola un mensaje que notifique la actividad y, si lo desea, que envíe los
datos resultantes. Como el método OnEvent recibe una referencia a ActivityExecutionContext
por mediación del parámetro Sender, es posible cerrar la actividad llamando al método
CloseActivity.
46
Windows Workflow Foundation 4.0 2011
Si desea crear una actividad que pueda actuar como receptor de eventos (por ejemplo, la
actividad HandleExternalEvent), también debe implementar la interfaz IEventActivity. Esta
interfaz define las responsabilidades principales de la actividad para escuchar eventos:
Esta interfaz permite indicar a la actividad que se suscriba a eventos antes de ejecutarse y
comunica a la actividad cuándo debe anular la suscripción. En los métodos de suscripción y
anulación de la suscripción, la actividad tiene la responsabilidad de garantizar la creación de una
cola con QueueName, así como su eliminación al final del procesamiento. Asimismo, ésta es la
ocasión apropiada para que la actividad registre información con los servicios locales que
ejecutarán la lógica en su nombre y que responderán poniendo en cola un mensaje.
Un servicio local es una clase que se define y agrega al tiempo de ejecución del flujo de trabajo
desde el host y del que se sirven el código del host, el flujo de trabajo o las actividades. El
servicio local puede mantener controladores de eventos u otras escuchas siempre que la
aplicación host se encuentre en ejecución; además, asegura que el flujo de trabajo obtenga los
datos apropiados poniendo en cola el mensaje. La información que se pasa al servicio local debe
incluir el nombre de la cola, el Id. de la instancia del flujo de trabajo y cualquier otro dato que
necesite el servicio para iniciar el trabajo o devolver un resultado a la actividad.
El código de ejemplo incluye una actividad de evento personalizada que crea una cola y registra
un controlador para recibir una notificación siempre que llegue algún evento a ella. El programa
host se limita a poner en cola un elemento tras un breve período para mostrar este proceso; si se
tratara de una situación real, es probable que el servicio local tuviera que responsabilizarse de
enviar los datos. En cualquier caso, de este modo demostramos que también el host puede poner
en cola datos para las actividades.
47
Windows Workflow Foundation 4.0 2011
Control de errores
Otra de las responsabilidades que asume el desarrollador de actividades consiste en controlar las
condiciones de error. La administración de errores en las actividades comparte muchas de sus
características con la realizada con cualquier otro código, salvo en que han de tenerse en cuenta
ciertas consideraciones especiales a la hora de administrar la ejecución de las actividades. Si se
produce algún error en la lógica de ejecución de las actividades, hay que generar una excepción
con tantos detalles como sean necesarios, tal como se haría con cualquier otro componente. Así
se indica el error al tiempo de ejecución, el cual puede interactuar con las actividades del flujo
de trabajo con el fin de darles ocasión de cerrarse correctamente o bien puede invocar
controladores especiales de errores.
Cada vez que se genera una excepción desde el código de ejecución de las actividades, se llama
al método HandleFault de la actividad. En el método HandleFault, debe escribir el código
preciso para liberar los recursos adecuados o para cancelar las operaciones asincrónicas
iniciadas por la actividad. Recuerde que la excepción se seguirá generando en el tiempo de
ejecución; este método sirve tan sólo para permitir la limpieza de la actividad. Además, las
actividades compuestas también admiten FaultHandlers, un método secundario adjunto especial
que se ejecuta como utilidad posterior al procesamiento después de que la actividad compuesta
haya pasado del estado de error al estado cerrado. La vista FaultHandlers sirve para modelar el
control de los errores generados desde las actividades secundarias. De este modo, al poner en
relación las excepciones con problemas concretos, se facilita la creación de un código mejor
para el control de errores en el flujo de trabajo.
Fíjese en que, en general, la cancelación se usa para implementar una semántica en la que una
actividad compuesta genera varias secundarias por lo que, a fin de cumplir la semántica
deseada, debe cancelar la ejecución continua de algunas secundarias. La cancelación es positiva
y se emplea para permitir la ejecución hacia delante; los errores, en cambio, son negativos y se
utilizan para implementar casos excepcionales. La cancelación y el control de errores son dos
conceptos totalmente diferentes. La implementación de la clase base de HandleFault sólo llama
al método Cancel cuando hay que habilitar escenarios muy básicos.
48
Windows Workflow Foundation 4.0 2011
Experiencia de diseño
Muchas actividades están diseñadas para su uso en interfaces de usuario basadas en modelos,
como el diseñador incluido con Visual Studio Extensions para Windows Workflow Foundation.
La experiencia de diseño de las actividades es, en muchos aspectos, más importante que los
principios fundamentales de ejecución, ya que resulta más visible para los demás
desarrolladores y para los usuarios de la actividad. Windows Workflow Foundation facilita la
visualización de flujos de trabajo en distintas situaciones, no sólo durante el desarrollo, por lo
que reviste vital importancia que la actividad no sólo respete la semántica de sus
responsabilidades sino que, además, resulte lógica y útil para los usuarios.
Para crear un diseñador, debe crear una clase derivada de la clase base ActivityDesigner o de
cualesquiera de los diseñadores de actividades compuestas disponibles en las bibliotecas de
Windows Workflow Foundation. Éste sería el resultado al aplicar SwitchActivityDesigner a la
actividad Switch:
[Designer(typeof(SwitchActivityDesigner),
typeof(IDesigner))]
public partial class SwitchActivity :
System.Workflow.ComponentModel.CompositeActivity,
IActivityEventListener<ActivityExecutionStatusChangedEventArgs>
...
Centremos en las características clave que se usan más a menudo en los diseñadores
personalizados. La primera de ellas es la capacidad para proporcionar elementos de menús
contextuales personalizados en la actividad que permitan al usuario iniciar una acción. Si omite
la propiedad Verbs en el diseñador, puede especificar la colección de elementos de menú que se
debe agregar al menú contextual de la actividad para que el usuario pueda hacer clic con el
botón secundario o hacer emerger de cualquier otra forma el menú contextual con intención de
iniciar la acción. Por cada verbo agregado a la colección, hay que suministrar un controlador de
eventos al que llamar cuando el usuario elija el elemento del menú. Además, debe pasar un
miembro de la enumeración DesignerVerbGroup que indique cómo se agrupa ese verbo
concreto en el menú contextual. Así puede agrupar actividades relacionadas según su propósito,
por ejemplo, las opciones de edición o las de configuración.
49
Windows Workflow Foundation 4.0 2011
Probablemente, la necesidad más común de tiempo de diseño que acucia a los desarrolladores
de actividades radica en la capacidad para personalizar la apariencia de las actividades en la
superficie de diseño. Windows Workflow Foundation ofrece varios mecanismos para crear la
apariencia deseada: desde opciones muy simples para establecer sólo algunas propiedades, hasta
las más avanzadas que permiten pintar la actividad directamente con un objeto
System.Drawing.Graphics.
Con respecto a la apariencia de una actividad de un flujo de trabajo, lo primero que se debe
comprender es que forma parte de lo que se denomina tema de diseñador. Un tema no es ni más
ni menos que una definición del aspecto que ha de tener cada actividad en el diseñador. Si tiene
instalado el producto Visual Studio Extensions para Windows Workflow Foundation y elige
Opciones en el menú Herramientas, verá una categoría para Workflow Designer con dos temas
instalados. Haga clic en el botón de creación para conocer las propiedades disponibles para cada
actividad. Los temas se pueden guardar y aplicar en el diseñador de Visual Studio pero, además,
también se pueden usar si se realoja el control del diseñador de flujos de trabajo en la aplicación
oportuna. Los temas permiten cambiar por completo la superficie de diseño de flujos de trabajo,
así como cada una de las actividades alojadas en el diseñador.
50
Windows Workflow Foundation 4.0 2011
Además del color y del diseño, se puede especificar que se dibuje un icono en una posición
predeterminada de la actividad. El icono se encuentra conectado a la actividad con el atributo
ToolboxBitmap y especifica un archivo de imagen (suele ser un archivo PNG o de mapa de bits
de 16×16) integrado en el ensamblado a modo de recurso incrustado. Además de utilizarse en el
diseñador, esta misma imagen aparece al agregar la actividad al cuadro de herramientas ya sea
de forma manual o con un instalador, algo lógico por otra parte teniendo en cuenta el nombre
del atributo. En la siguiente imagen se muestra la actividad CreateUser dentro de un flujo de
trabajo junto con el tema y el icono.
Durante la creación de diseñadores para actividades compuestas, no sólo debe preocuparse por
los temas y los iconos, sino también por trazar conectores entre los diseñadores de actividades
secundarias o por cambiar de cualquier otro modo la apariencia de inclusión de esas
secundarias. No obstante, existen varias clases base que ofrecen la funcionalidad precisa para
51
Windows Workflow Foundation 4.0 2011
reducir la cantidad de código que se debe escribir. En el caso de la actividad Switch, por
ejemplo, el diseñador se deriva de ParallelActivityDesigner, que permite dibujar las actividades
secundarias como ramas y crea un verbo de diseñador para agregar ramas nuevas.
Así, el diseñador de la actividad Switch sólo tiene que omitir un método y devolver una
actividad SwitchBranchActivity nueva. Este diseñador demuestra su utilidad en las actividades
compuestas con ramas; se emplea de forma interna en las actividades IfElse, Parallel y Listen.
Un último apunte: al crear una actividad compuesta con el diseñador de actividades, se muestra
en la superficie de diseño con una representación de todas sus actividades secundarias; por lo
tanto, el usuario de la actividad compuesta verá todas las actividades internas de la
implementación. Si es lo que pretende, no pasa nada pero, de lo contrario, puede solucionarlo
creando un diseñador para la actividad compuesta que se derive de la clase base
ActivityDesigner. Así se ofrece la representación sencilla de una única actividad. Si lo desea,
adjunte un tema de diseñador o atributos ToolboxBitmap para personalizar más el aspecto y
ofrecer una auténtica encapsulación.
Validación
A la hora de crear una actividad o cualquier otro componente, resulta recomendable validar la
entrada del usuario y asegurarse de que la configuración del componente es correcta. De hecho,
lo ideal sería poder impedir que el usuario configure de manera incorrecta el componente.
Existen dos áreas clave de desarrollo donde se ofrece la oportunidad de garantizar la correcta
configuración de la actividad: en el diseñador y con un validador personalizado de la actividad.
Cuando se crea un diseñador personalizado para la actividad, se controlan tanto las actividades
susceptibles de adición a la actividad compuesta como las actividades a las que se puede agregar
la actividad en cuestión. Es importante apuntar que este comportamiento sólo se aplica al
entorno de diseño, es decir, que no desempeña papel alguno al agregar la actividad mediante
código.
52
Windows Workflow Foundation 4.0 2011
actividad compuesta. El uso de los dos métodos anteriores facilita el control de la estructura de
actividades relacionada con su actividad. Esto reviste especial importancia al comprobar las
necesidades de ejecución de la actividad, porque ofrece la oportunidad de garantizar que su
configuración permite la correcta ejecución.
La otra opción para validar la actividad consiste en crear un validador personalizado. La tarea de
la clase del validador consiste en inspeccionar la actividad y comprobar que su configuración
respete los requisitos. Esta validación tiene lugar aunque se emplee un diseñador para agregar la
actividad al flujo de trabajo. A estas alturas, es probable que ya haya adivinado cómo se crea un
validador: debe crear una clase que se derive de ActivityValidator y, a continuación, omitir el
método Validate; luego, ha de usar ActivityValidatorAttribute para conectar el validador con la
actividad.
Aunque la actividad CreateUser cuenta con una propiedad para alojar la contraseña, no es
recomendable configurar la contraseña de forma estática en el flujo de trabajo. En lugar de
hacerlo así, el componente de validación garantiza que la propiedad de contraseña esté enlazada
a algún otro valor para que su valor se establezca en tiempo de ejecución. En la figura 9 se
muestra cómo prueba la propiedad la clase CreateUserValidator a fin de asegurar que esté
enlazada.
El código valida en primer lugar que la actividad sea del tipo correcto y que se esté validando en
otro contexto que no sea el de su propia compilación. Si no comprueba si la propiedad primaria
tiene un valor Null, no podrá crear siquiera la actividad, ya que el validador se ejecutará al
compilarla. ValidationErrorCollection sirve para devolver la recopilación de errores al
diseñador de manera que se agreguen los mensajes de error adecuados a la interfaz de usuario.
53
Windows Workflow Foundation 4.0 2011
DISEÑADORES ALOJADOS
¿Qué pasa si quieres crear una actividad personalizada? Muchos de los productos permiten a los
usuarios finales personalizar flujos de trabajo. Windows Workflow Foundation 4 le permite
acoger el diseñador en una aplicación con bastante facilidad.
1. Añadir una nueva aplicación WPF, para ello seguir los siguientes pasos:
a. Botón derecho en la solución con la que hemos estado trabajando hasta ahora y
añadir un nuevo proyecto
i. System.Activities.Presentation
ii. System.Activities.Core.Presentation
iii. System.Activities
i. HolaMundo.Ativities
ii. HolaMundo.Activities.Designers
<Window x:Class="HelloDesigner.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation
"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Name="grid1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
<TextBox Grid.Row="1" Name="textXAML"
VerticalScrollBarVisibility="Visible" />
54
Windows Workflow Foundation 4.0 2011
</Grid>
</Window>
using System.Activities.Presentation;
using System.Activities.Statements;
using System.Activities.Presentation.Toolbox;
using System.Activities.Core.Presentation;
using System.Activities.Presentation.Metadata;
using System.ComponentModel;
using HelloWorkflow.Activities;
using HelloWorkflow.Activities.Designers;
Cuando usted aloja el diseñador puede controlar la caja de herramientas. Elige lo que los
controles van a aparecer, las categorías que aparecen en el e incluso los nombres de los
controles. Agregue la función CreateToolboxControl según las indicaciones.
55
Windows Workflow Foundation 4.0 2011
j. La venta del diseñador muestra el XAML del flujo de trabajo. Para hacer esto
necesitamos una función que maneje el evento ModelChanged. Añadir la
función ShowWorkflowXAML como se muestra.
public MainWindow()
{
InitializeComponent();
RegisterMetadata();
AddDesigner();
}
56
Windows Workflow Foundation 4.0 2011
57
Windows Workflow Foundation 4.0 2011
EJEMPLOS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
namespace ActivityLibrary1
{
58
Windows Workflow Foundation 4.0 2011
6. Haga clic en el botón Argumentos, situado en la parte inferior izquierda del diseñador
de actividad, para mostrar el recuadro Argumentos.
10. Escriba Result en el cuadro Nombre que se encuentra debajo del argumento
BookmarkName recién agregado, seleccione Salida en la lista desplegable Dirección,
seleccione Int32 en la lista desplegable Tipo de argumento y, a continuación, presione
ENTRAR.
13. Haga clic en el botón Argumentos en el lado inferior izquierdo del diseñador de
actividad para cerrar el recuadro Argumentos.
14. Arrastre una actividad Sequence de la sección Flujo de control del cuadro de
herramientas y colóquela en el diseñador de actividad
59
Windows Workflow Foundation 4.0 2011
1. Abra la solución del tema anterior Cómo: Crear una actividad con Visual Studio 2010.
60
Windows Workflow Foundation 4.0 2011
2. Arrastre una actividad Flowchart desde la sección Diagrama de flujo del cuadro de
herramientas y colóquela en la superficie de diseño de flujo de trabajo.
3. Haga clic en Argumentos en la parte inferior izquierda del diseñador de flujo de trabajo
para mostrar el recuadro Argumentos.
9. Haga clic en Variables en el lado inferior izquierdo del diseñador de flujo de trabajo
para mostrar el recuadro Variables.
2. Mantenga el mouse sobre el nodo de inicio en la parte superior del flujo de trabajo para
indicar que la actividad Assign es el punto de partida de Flowchart. Haga clic en uno
de los rectángulos que aparecen cuando el mouse se desplaza por el nodo de inicio y
arrástrelo a la parte de superior de la actividad Assign. Cuando el mouse está sobre la
actividad Assign, aparecen cuatro rectángulos. Arrástrelo para que la línea de conexión
de la parte inferior del nodo de inicio se conecte con el rectángulo superior de la
actividad Assign y, a continuación, suelte el botón del mouse.
61
Windows Workflow Foundation 4.0 2011
8. Siga los pasos anteriores para conectar la actividad Prompt a la actividad Assign.
10. A rrastre otra actividad FlowDecision del cuadro de herramientas y colóquela debajo
de la primera. Conecte las dos actividades al arrastrar desde el rectángulo con la etiqueta
Falso en la actividad FlowDecision superior con rectángulo en la parte superior de la
segunda actividad FlowDecision
13. Haga clic en la actividad WriteLine situada más a la izquierda para seleccionarla y
escriba la siguiente expresión en el cuadro de valor de la propiedad Texto en la
Ventana Propiedades.
14. Conecte WriteLine al lado izquierdo de la actividad Prompt que está sobre ella.
62
Windows Workflow Foundation 4.0 2011
15. Haga clic en la actividad WriteLine situada más a la derecha para seleccionarla y
escriba la siguiente expresión en el cuadro de valor de la propiedad Texto en la
Ventana Propiedades.
16. Conecte la actividad WriteLine al lado derecho de la actividad Prompt que está sobre
ella.
using System;
using System.Linq;
using System.Activities;
using System.Activities.Statements;
using System.Threading;
using System.Collections.Generic;
namespace WorkflowConsoleApplication1
{
class Program
{
63
Windows Workflow Foundation 4.0 2011
64
Windows Workflow Foundation 4.0 2011
{
validEntry = true; wfApp.ResumeBookmark("EnterGuess", Guess);
}
}
}
}
}
}
5. En el cuadro Ubicación, escriba el directorio en el que desea guardar el proyecto o haga clic
en Examinar para navegar hasta él.
65
Windows Workflow Foundation 4.0 2011
<Window
x:Class="Microsoft.Samples.UsingWorkflowItemPresenter.RehostingWfDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sapt="clr-
namespace:System.Activities.Presentation.Toolbox;assembly=System.Activities.Pr
esentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="Window1"
Height="600" Width="900"> <Window.Resources> <sys:String
x:Key="AssemblyName">System.Activities, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35</sys:String> </Window.Resources> <Grid>
<Grid.ColumnDefinitions> <ColumnDefinition Width="2*"/> <ColumnDefinition
Width="7*"/> <ColumnDefinition Width="3*"/> </Grid.ColumnDefinitions> <Border
Grid.Column="0"> <sapt:ToolboxControl Name="Toolbox"> <sapt:ToolboxCategory
CategoryName="Basic"> <sapt:ToolboxItemWrapper AssemblyName="{StaticResource
AssemblyName}" > <sapt:ToolboxItemWrapper.ToolName>
System.Activities.Statements.Sequence </sapt:ToolboxItemWrapper.ToolName>
</sapt:ToolboxItemWrapper>
<sapt:ToolboxItemWrapper AssemblyName="{StaticResource AssemblyName}">
<sapt:ToolboxItemWrapper.ToolName> System.Activities.Statements.WriteLine
</sapt:ToolboxItemWrapper.ToolName> </sapt:ToolboxItemWrapper>
<sapt:ToolboxItemWrapper AssemblyName="{StaticResource AssemblyName}">
<sapt:ToolboxItemWrapper.ToolName> System.Activities.Statements.If
</sapt:ToolboxItemWrapper.ToolName> </sapt:ToolboxItemWrapper>
<sapt:ToolboxItemWrapper AssemblyName="{StaticResource AssemblyName}">
<sapt:ToolboxItemWrapper.ToolName> System.Activities.Statements.While
</sapt:ToolboxItemWrapper.ToolName> </sapt:ToolboxItemWrapper>
</sapt:ToolboxCategory> </sapt:ToolboxControl> </Border> <Border
Grid.Column="1" Name="DesignerBorder"/> <Border Grid.Column="2"
Name="PropertyBorder"/> </Grid> </Window>
Para asociar un diseñador de actividad a un tipo de actividad, debe registrar ese diseñador
de actividad con el almacén de metadatos. Para ello, agregue el método RegisterMetadata
a la clase RehostingWFDesigner. Dentro del ámbito del método RegisterMetadata, cree un
objeto AttributeTableBuilder y llame al método AddCustomAttributes para agregar los
atributos a él. Llame al método AddAttributeTable para agregar AttributeTable al almacén
de metadatos. El siguiente código contiene la lógica de rehospedaje para el diseñador.
Registra los metadatos, coloca SimpleNativeActivity en el cuadro de herramientas y crea el
flujo de trabajo. Coloque este código en el archivo RehostingWFDesigner.xaml.cs.
using System;
using System.Activities.Core.Presentation;
using System.Activities.Presentation;
using System.Activities.Presentation.Metadata;
using System.Activities.Presentation.Toolbox;
using System.Activities.Statements;
using System.ComponentModel;
using System.Windows; namespace UsingWorkflowItemPresenter
{
// Interaction logic for RehostingWFDesigner.xaml
public partial class RehostingWFDesigner
{
public RehostingWFDesigner()
{
InitializeComponent();
}
66
Windows Workflow Foundation 4.0 2011
System.Data.DataSetExtensions.dll
System.Activities.Presentation.dll
System.ServiceModel.Activities.dll
<sap:ActivityDesigner
x:Class="Microsoft.Samples.UsingWorkflowItemPresenter.SimpleNativeDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sap="clr-
namespace:System.Activities.Presentation;assembly=System.Activities.Presentati
on" xmlns:sapv="clr-
namespace:System.Activities.Presentation.View;assembly=System.Activities.Prese
ntation"> <sap:ActivityDesigner.Resources>
<DataTemplate x:Key="Collapsed"> <StackPanel> <TextBlock>This is the collapsed
view</TextBlock> </StackPanel> </DataTemplate> <DataTemplate x:Key="Expanded">
<StackPanel> <TextBlock>Custom Text</TextBlock> <sap:WorkflowItemPresenter
Item="{Binding Path=ModelItem.Body, Mode=TwoWay}" HintText="Please drop an
activity here" /> </StackPanel> </DataTemplate> <Style
x:Key="ExpandOrCollapsedStyle" TargetType="{x:Type ContentPresenter}"> <Setter
Property="ContentTemplate" Value="{DynamicResource Collapsed}"/>
<Style.Triggers> <DataTrigger Binding="{Binding Path=ShowExpanded}"
Value="true"> <Setter Property="ContentTemplate" Value="{DynamicResource
Expanded}"/> </DataTrigger> </Style.Triggers> </Style>
67
Windows Workflow Foundation 4.0 2011
using System.Activities;
namespace Microsoft.Samples.UsingWorkflowItemPresenter
{
public sealed class SimpleNativeActivity : NativeActivity {
25. Seleccione Iniciar sin depurar en el menú Depurar para abrir la ventana del diseño
personalizado rehospedado.
68