Archive for December, 2007

Actualizando una aplicación CAB a SCSF

Este artículo describe como actualizar una aplicación CAB a Smart Client Software Factory 2007.

Contenidos

  • Requisitos
  • Tarea 1: Creando una solución nueva de Smart Client
  • Tarea 2: Agregando la aplicación CAB antigua
  • Tarea 3: Removiendo el proyecto Shell de Smart Client
  • Tarea 4: Actualizando el proyecto Shell antiguo
  • Tarea 5: Modificando el archivo de la solución
  • Tarea 6: Compile y Ejecute… Diviértase! :)

Requisitos

Para poder completar la actualización, debe tener lo siguiente instalado en su computadora:

Tarea 1: Creando una solución nueva de Smart Client

Para actualizar su solución, creará una nueva solución de Smart Client usando la plantilla Smart Client Solution y luego agregará los módulos de su solución y el proyecto Shell a la nueva solución.

1. En el Visual Studio, dirígase a New (Nuevo) en el menú File (Archivo), y luego haga click en Project (Proyecto).

500x339.aspx

Figura 1. Las plantillas Smart Client Application Solution.

2. En el diálogo de New Project (Nuevo Proyecto), expanda el nodo de Guidance Packages. Haga click en el tipo de proyecto Smart Client Development May 2007.

3. En la parte de Templates (Plantillas), seleccione Smart Client Application (C#) o Smart Client Application (Visual Basic) (dependiendo del lenguaje en el que haya codificado la aplicación CAB).

4. Cambie el Name (Nombre).

5. (Opcional) Cambie la ubicación de la solución.

6. Haga click en OK (Aceptar).

500x290.aspx

Figura 2. El asistente Create Solution.

7. Ingrese la ubicación de los ensamblados del Composite UI Application Block, Enterprise Library, y de los offline application blocks.

8. Ingrese el Root namespace para su aplicación.

9. Desmarque la opción Create a separate module to define the layout for the shell (Crear un módulo separado para definirel diseño de la Shell).

10. (Opcional) Seleccione la opción Allow solution to host WPF SmartParts (Permitir que la solución albergue WPF SmartParts) (si su solución contiene o contendrá WPF SmartParts).

11. (Opcional) Seleccione la opción Show documentation after recipe completes (Mostrar documentación luego de que se complete el asistente).

12. Haga click Finish (Finalizar).

NewSCSFSolutionExplorer

Figura 3. La estructura de una solución de Smart Client.

Tarea 2: Agregando la aplicación CAB antigua

En esta tarea, agregará su aplicación CAB a la solución nueva de Smart Client y la configurará de acuerdo con la estructura de SCSF.

1. Copie su aplicación CAB antigua a la carpeta Source ubicada dentro de la carpeta raíz de su solución de Smart Client nueva.

2. En el Solution Explorer, haga click derecho sobre la carpeta Source, dirígase a Add (Agregar), y luego haga click en Existing Project (Proyecto Existente).

3. Busque el directorio de la aplicación CAB antigua y agregue uno de los proyectos de módulo (ej.: su proyecto del módulo Shell de CAB).

234x375.aspx

Figura 4. Proyecto del módulo Shell de CAB agregado.

4. Repita los pasos 2 y 3 hasta que todos los módulos hayan sido agregados.

5. Haga click derecho sobre su Shell de CAB y seleccione Set as StartUp Project (Establecer como proyecto de inicio).

6. Por cada módulo, haga click derecho sobre el proyecto y seleccione Add Reference (Agregar Referencia). En el tab de Projects (Proyectos), seleccione los proyectos Infrastructure.Interface e Infrastructure.Library y haga click en OK (Aceptar).

7. Por cada módulo, reemplace los ensamblados Microsoft.Practices.* con los que están ubicados en %CarpetaRaízDeLaSolución%\Lib. Si tiene referencias a los proyectos CompositeUI y CompositeUI.WinForms, reemplacelos por las referencias a los ensamblados ubicados en %CarpetaRaízDeLaSolución%\Lib.

Nota: %CarpetaRaízDeLaSolución%\Lib es el directorio de la carpeta raíz en la cual ubicó la nueva solución de Smart Client.

8. Por cada módulo, haga click derecho sobre el proyecto y seleccione Properties (Propiedades). En el tab de Build (Construir), dirígase a la sección Output (Salida) y edite el directorio de Output (Salida) a %CarpetaRaízDeLaSolución%\bin\Debug.

500x353.aspx

Figura 5. Output Path (Directorio de Salida) en la sección de Output (Salida) ubicada en el tab de Build (Construir) en las propiedades del Proyecto. Nota: quizás no vea un directorio relativo hasta que cierre la ventana de propiedades y la vuelva a abrir.

Tarea 3: Removiendo el proyecto Shell de Smart Client

En esta tarea, removerá el proyecto Shell de Smart Client.

1. En el Solution Explorer, haga click derecho sobre el proyecto Infrastructure.Shell y luego haga click en Remove (Remover).

199x375.aspx

Figura 6. Removiendo el proyecto Shell de SCSF.

2. Elimine la carpeta Source\Infrastructure\Shell ubicada dentro de la carpeta raíz de la solución.

500x288.aspx

Figura 7. Eliminando la carpeta Shell.

Tarea 4: Actualizando el proyecto Shell

En esta tarea, actualizará el proyecto Shell de su aplicación CAB para reemplazar al proyecto Shell de Smart Client.

1. En el Solution Explorer, expanda su proyecto Shell, abra el archivo ProfileCatalog.xml y actualícelo para que concuerde con el esquema usado en las soluciones de SCSF. Por ejemplo, si su ProfileCatalog aparece así:

XML

 <?xml version=”1.0″ encoding=”utf-8″ ?>

<SolutionProfile xmlns=”http://schemas.microsoft.com/pag/cab-profile” >

    <Modules>

        <!– algunos modulos –>

    </Modules>

</SolutionProfile>

Deberá actualizarlo para que aparezca así:

XML

 <SolutionProfile xmlns=”http://schemas.microsoft.com/pag/cab-profile/2.0″>

   <Section Name=”Services”>

      <Modules>

         <ModuleInfo AssemblyFile=”Infrastructure.Module.dll” /> <!– ESTO ES REQUERIDO POR LAS SOLUCIONES SC-SF –>

         <!– UBIQUE LOS MÓDULOS DE INFRAESTRUCTURA (FOUNDATIONAL) AQUÍ –>

      </Modules>

   </Section>

   <Section Name=”Apps”>

      <Dependencies>

         <Dependency Name=”Services” />

      </Dependencies>

      <Modules>

         <!– UBIQUE LOS MÓDULOS DE NEGOCIO (BUSINESS) AQUÍ –>

      </Modules>

   </Section>

</SolutionProfile>

 

2. Haga click en Save (Guardar) y cierre el archivo.

3. Ahora, haga click derecho sobre su archivo ShellApplication.cs y seleccione View Code (Ver Código).

4. Agregue la siguiente línea:

Visual Basic

Imports %RootNamespace%.Infrastructure.Library;
C#

using %RootNamespace%.Infrastructure.Library;
Nota: %RootNamespace% debe ser reemplazado con el RootNamespace que especificó al crear la solución de Smart Client.

5. Actualice la firma de la clase para que herede de FormShellApplication en vez de SmartClientApplication.

6. Haga click en Save (Guardar).

Tarea 5: Modificando el archivo de la solución

En esta tarea, modificará el archivo suSolución.sln para terminar de establecer el proyecto Shell de su aplicación CAB como el de Smart Client.

1. En la carpeta raíz de su solución, haga click derecho sobre el archivo .sln, seleccione Open with (Abrir con) y elija el NotePad (Bloc de notas).

2. Localice la sección Project de su proyecto Shell.

500x224.aspx

Figura 8. Sección del proyecto Shell.

3. Copie al portapapeles el GUID que aparece luego de la ubicación del proyecto (su formato es “XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”).

1

Figura 9. El GUID que aparece luego de la ubicación del proyecto.

4. Localice la línea GlobalSection(ExtensibilityGlobals) = postSolution.

5. Reemplace el GUID especificado en la propiedad ShellProjectGuid con la GUID de su proyecto Shell.

500x224.as1px

Figura 10. ShellProjectGuid.

6. Guarde y cierre el archivo.

Tarea 6: Compile y Ejecute… Diviértase! :)

En esta tarea, concluirá compilando y ejecutando su solución actualizada.

1. Vuelva al Visual Studio. Aparecerá un mensaje indicando que la solución ha sido modificada fuera del ambiente de desarrollo. Haga click en Reload (Recargar) para recargar la solución.

2. Compile (Build) y ejecute la aplicación.

Felicidades! Usted ha actualizado su aplicación CAB a SCSF May 2007! :) Debería poder utilizar las recipes (asistentes) ahora.

- Salu2, Nacho

See this topic in English.

Upgrading a CAB application to SCSF

This post describes how to upgrade a CAB application to Smart Client Software Factory 2007.

Contents

  • Prerequisites
  • Task 1: Creating a new Smart Client solution
  • Task 2: Adding the old CAB application
  • Task 3: Removing the Smart Client template Shell project
  • Task 4: Upgrading the old Shell
  • Task 5: Modifying the solution file
  • Task 6: Compile and Run… Have fun! :)

Prerequisites

In order to complete the upgrade, you must have the following installed on your computer:

Task 1: Creating a new Smart Client solution

To upgrade your solution, you will create a new smart client solution using the Smart Client Solution template and then you will add your solution’s modules and Shell project to the new solution.

1. In Visual Studio, point to New on the File menu, and then click Project.

500x339.aspx

Figure 1. The Smart Client Application solution templates.

2. In the New Project dialog box, expand the Guidance Packages node. Click the Smart Client Development May 2007 project type.

3. In the Templates window, select Smart Client Application (C#) or Smart Client Application (Visual Basic) (depending on the language you’ve coded the CAB application).

4. Change the Name.

5. (Optional) Change the location for the solution.

6. Click OK.

500x290.aspx

Figure 2. The Create Solution recipe wizard.

7. Enter the location of the Composite UI Application Block, Enterprise Library, and the offline application blocks assemblies.

8. Enter the Root namespace for your application.

9. Unselect the option Create a separate module to define the layout for the shell.

10. (Optional) Select the Allow solution to host WPF SmartParts check box (if your solution contains or will contain WPF SmartParts).

11. (Optional) Select the Show documentation after recipe completes check box.

12. Click Finish.

NewSCSFSolutionExplorer

Figure 3. The smart client solution structure.

Task 2: Adding the old CAB application

In this task you will add your CAB application to the new Smart Client solution and configure it according to the SCSF structure.

1. Copy your old CAB application to the Source folder located inside the new Smart Client solution root folder.

2. In Solution Explorer, right-click the Source solution folder, point to Add, and then click Existing Project.

3. Browse the directory of the old CAB application and add one of the module projects (i.e.: your CAB Shell module project).

234x375.aspx

Figure 4. CAB Shell module project added.

4. Repeat steps 2 and 3 until all of the modules have been added.

5. Right-click your CAB Shell and select Set as StartUp Project.

6. For each module, right-click the project and select Add Reference. In the Projects tab, select the Infrastructure.Interface and Infrastructure.Library projects and click OK.

7. For each module, replace the Microsoft.Practices.* assemblies with the ones located in %RootSolutionFolder%\Lib. If you have references to the CompositeUI and CompositeUI.WinForms projects, replace those references to the assemblies located in % RootSolutionFolder %\Lib.

Note: % RootSolutionFolder %\Lib is the directory of the root folder where you placed the new Smart Client solution.

8. For each module, right-click the project and select Properties. In the Build tab, go to the Output section and edit the Output path to %RootSolutionFolder%\bin\Debug.

 500x353.aspx

Figure 5. Output path in the Output section located at Build tab in the Proyect properties. Note: you might not see a relative path until you close the properties window and open it again.

Task 3: Removing the Smart Client template Shell project

In this task you will remove the Smart Client Shell template project.

1. In Solution Explorer, right-click the Infrastructure.Shell project and then click Remove.

199x375.aspx

Figure 6. Removing the SCSF Shell project.

2. Delete the Source\Infrastructure\Shell folder located in within the root folder of the solution.

500x288.aspx

Figure 7. Deleting the SCSF Shell folder.

Task 4: Upgrading the old Shell

In this task you will upgrade the Shell of your CAB application in order to replace the Smart Client Shell project.

1. In Solution Explorer, expand your Shell project, open the ProfileCatalog.xml file and update it to match the schema used in SCSF solutions. For example, if your profile catalog looks like this:

XML

<?xml version=”1.0″ encoding=”utf-8″ ?><SolutionProfile xmlns=”http://schemas.microsoft.com/pag/cab-profile” >

    <Modules>

        <!– algunos modulos –>

    </Modules>

</SolutionProfile>

You have to update it to look like this:

XML

 <SolutionProfile xmlns=”http://schemas.microsoft.com/pag/cab-profile/2.0″>

   <Section Name=”Services”>

      <Modules>

         <ModuleInfo AssemblyFile=”Infrastructure.Module.dll” /> <!– ESTO ES REQUERIDO POR LAS SOLUCIONES SC-SF –>

         <!– UBIQUE LOS MÓDULOS DE INFRAESTRUCTURA (FOUNDATIONAL) AQUÍ –>

      </Modules>

   </Section>

   <Section Name=”Apps”>

      <Dependencies>

         <Dependency Name=”Services” />

      </Dependencies>

      <Modules>

         <!– UBIQUE LOS MÓDULOS DE NEGOCIO (BUSINESS) AQUÍ –>

      </Modules>

   </Section>

</SolutionProfile>

2. Click Save and close the file.

3. Now, right-click your ShellApplication.cs file and select View Code.

4. Add the following statement:

Visual Basic

 Imports %RootNamespace%.Infrastructure.Library;
C#

 using %RootNamespace%.Infrastructure.Library;
Note: %RootNamespace% must be replaced with the RootNamespace you specified when you created the Smart Client solution.

5. Update the class signature to inherit from FormShellApplication instead of SmartClientApplication.

6. Click Save.

Task 5: Modifying the solution file

In this task you will modify the yourSolution.sln file in order to finish setting the Shell of the CAB application as the Smart Client Shell.

1. In the root folder of your solution, right-click the .sln file, select Open with and then select the NotePad.

2. Locate the Project section for the Shell project.

500x224.aspx 

Figure 8. Shell Project section.

3. Copy to the clipboard the GUID that appears after the project location (its format is “XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”).

 1

Figure 9. The GUID that appears after the project location.

4. Locate the line GlobalSection(ExtensibilityGlobals) = postSolution.

5. Replace the GUID specified in the ShellProjectGuid property with your Shell project’s GUID.

 500x224.as1px

Figure 10. ShellProjectGuid.

6. Save and close the file.

Task 6: Compile and Run… Have fun! :)

In this task you will finish building and running your upgraded solution.

1. Go back to Visual Studio. A message saying that the solution has been modified outside of the development environment will appear. Click Reload to reload the solution.

2. Build and run the application.

Congratulations! You have upgraded your CAB application to SCSF May 2007! :) You should be able to run recipes now.

- Cheers, Nacho

Ver este tópico en español.

Cómo: Desechar una Vista (SmartPart) en CAB y SCSF (Dispose a View)

En el foro de Smart Client en Codeplex, varios han preguntado cómo desechar una vista. Además, varias soluciones fueron propuestas.

La solución más rápida era extender el método CloseView() en el Presenter (de la Vista que queríamos desechar) de la siguiente manera:

public void OnCloseView()
{
    base.CloseView();

    WorkItem.SmartParts.Remove(View); //Removes the view from the SmartPart collection.
    if (View is IDisposable) ((IDisposable)View).Dispose(); //Disposes the view.
}

Sin embargo, quizás querramos desechar cualquier vista cada vez que la cerremos, por lo que la mejor forma de lograr ésto es mandando este código a la clase base Presenter localizada en el proyecto Infrastructure.Interface. JochenZ me mostró una forma ampliada de hacerlo (en el tópico SmartParts do not get disposed on WorkItem.Terminate(), en Codeplex). En su código, JochenZ consideró la posibilidad de que algún subscriptor al evento SmartPartClosing quizás haya establecido la propiedad Cancel en True, evitando que la Vista se cerrara. Es un código bien hecho, así que lo citaré:

protected virtual void CloseView()
{
    Services.IWorkspaceLocatorService locator = WorkItem.Services.Get<Services.IWorkspaceLocatorService>();
    IWorkspace wks = locator.FindContainingWorkspace(WorkItem, View);

    if (wks != null)  wks.Close(View);

   // check whether the view was actually closed (a subscriber to the IWorkspace.SmartPartClosing event might have cancelled it)
    wks = locator.FindContainingWorkspace(WorkItem, View);

    // if the view was removed from the workspace, remove it from the smartparts collection and dispose it if possible
    if (wks == null) {
        WorkItem.SmartParts.Remove(View);
        IDisposable viewAsDisposable = View as IDisposable;
        if (viewAsDisposable != null) viewAsDisposable.Dispose();
    }
}

Debo admitir que encuentro bastante interesante el código citado arriba, pero también debo decir que las soluciones propuestas hasta aquí presentan una falla. Como podemos ver, el método CloseView() llama al método IWorkspace.Close(smartPart) para cerrar la vista (obviamente :P ). Pero, ¿qué pasaría si un botón, por ejemplo, en otro lugar (por así decirlo, en el Shell o en otra vista) llamara directamente al método IWorkspace.Close(smartPart)? ¡No habría llamada al método CloseView() por lo que la vista no se desecharía! Por lo tanto, necesitamos encontrar un nuevo hogar para el procedimiento de disposing.

Un nuevo hogar podría ser una clase que proveyera un método estático para hacer el disposing, la cuál podríamos ubicar en el proyecto Infrastructure.Interface (por razones de uso :) ). El código resultante debería verse así:

public class ViewDisposer
{
    ///
    /// Disposes the closing view.
    ///
    /// Closing SmartPart.
    /// Container WorkItem.

    public static void DiposeView(object smartPart, WorkItem workItem)
    {
        IDisposable viewAsDisposable = smartPart as IDisposable;
        if (viewAsDisposable != null) viewAsDisposable.Dispose();
        workItem.SmartParts.Remove(smartPart);
    }
}

Una vez que tenemos ésto, podemos utilizarlo así (por ejemplo):

WorkItem.Workspaces[WorkspaceNames.RightWorkspace].SmartPartClosing += new EventHandler<WorkspaceCancelEventArgs>(
    delegate(object workspace, WorkspaceCancelEventArgs e)
        {               
            ViewDisposer.DisposeView(e.SmartPart, WorkItem);
        });

Por favor, recuerden que deben considerar cuándo y dónde hacer el disposing (si no quieren hacerlo todo el tiempo). Además, si se posiciona este handler en la primera posición (en cuanto a orden de handlers), no se podrá cancelar el diposing, por lo que recomiendo usar ésto cuidadosamente y, por supuesto, a conciencia! ;)

- Salu2, Nacho

See this topic in English.

How To: Dispose a view (SmartPart) when using CAB and SCSF

There have been several questions about disposing views at the Smart Client forum at CodePlex. Moreover, several workarounds have been proposed.

The fastest workaround was to extend the CloseView() method at the Presenter (of the View we want to dispose) as follows:

public void OnCloseView()
{
    base.CloseView();

    WorkItem.SmartParts.Remove(View); //Removes the view from the SmartPart collection.
    if (View is IDisposable) ((IDisposable)View).Dispose(); //Disposes the view.
}

However, we may want to dispose any view each time we close it, so the best way to achieve this is to send this code to the Presenter base class located at the Infrastructure.Interface project. JochenZ showed me an enhanced way to do this (in the topic SmartParts do not get disposed on WorkItem.Terminate() at CodePlex). In his code, JochenZ considered the possibility that a subscriber to the SmartPartClosing event may have set the Cancel property to True, preventing the View to close itself. It’s a nice piece of code, so I shall quote it:

 protected virtual void CloseView()
{
    Services.IWorkspaceLocatorService locator = WorkItem.Services.Get<Services.IWorkspaceLocatorService>();
    IWorkspace wks = locator.FindContainingWorkspace(WorkItem, View);

    if (wks != null)  wks.Close(View);

   // check whether the view was actually closed (a subscriber to the IWorkspace.SmartPartClosing event might have cancelled it)
    wks = locator.FindContainingWorkspace(WorkItem, View);

    // if the view was removed from the workspace, remove it from the smartparts collection and dispose it if possible
    if (wks == null) {
        WorkItem.SmartParts.Remove(View);
        IDisposable viewAsDisposable = View as IDisposable;
        if (viewAsDisposable != null) viewAsDisposable.Dispose();
    }
}

I must say that I find pretty interesting the code above, but I must also say that the workarounds showed up to here present a flaw. As we can see, the CloseView() method calls the IWorkspace.Close(smartPart) method in order to close the view (obviously :P ). But what would happen if a button, for example, in other place (let’s say the Shell or another view) calls directly the IWorkspace.Close(smartPart) method? There would be no call to the CloseView() method of the Presenter, so the view wouldn’t be disposed! So we need to find a new home for the disposing procedure.

A new home could be a class that provides a static method for disposing, which could be located in the Infrastructure.Interface project (for usability reasons :) ). The resulting code should look like this:

public class ViewDisposer
{
    ///
    /// Disposes the closing view.
    ///
    /// Closing SmartPart.
    /// Container WorkItem.
    public static void DiposeView(object smartPart, WorkItem workItem)
    {
        IDisposable viewAsDisposable = smartPart as IDisposable;
        if (viewAsDisposable != null) viewAsDisposable.Dispose();
        workItem.SmartParts.Remove(smartPart);
    }
}

Once we have this, we can use it as follows (for example):

WorkItem.Workspaces[WorkspaceNames.RightWorkspace].SmartPartClosing += new EventHandler<WorkspaceCancelEventArgs>(
    delegate(object workspace, WorkspaceCancelEventArgs e)
        {               
            ViewDisposer.DisposeView(e.SmartPart, WorkItem);
        });

Please, remember that you must consider when and where to dispose (if you don’t want to dispose at every time). Besides, if you place this handler in the first position (regarding handlers order), you won’t be able to cancel the disposal, so I recommend to use this carefully and, of course, consciously! ;)

- Cheers, Nacho

Ver este tópico en español.