Migración de proyectos de Silverlight Windows Phone a proyectos de UWP
El tema anterior era Namespace y asignaciones de clases.
Para comenzar el proceso de portabilidad, cree un nuevo proyecto de Windows 10 en Visual Studio y copie los archivos en él.
Crear el proyecto y copiar archivos en él
- Inicie Microsoft Visual Studio 2015 y cree un nuevo proyecto aplicación en blanco (Windows Universal). Para obtener más información, consulta Jumpstart your Windows Runtime 8.x app using templates (C#, C++, Visual Basic). El nuevo proyecto compila un paquete de aplicación (un archivo appx) que se ejecutará en todas las familias de dispositivos.
- En el proyecto de aplicación Windows Phone Silverlight, identifique todos los archivos de código fuente y los archivos de recursos visuales que desea reutilizar. Con Explorador de archivos, copie los modelos de datos, los modelos de vista, los recursos visuales, los diccionarios de recursos, la estructura de carpetas y cualquier otra cosa que desee volver a usar en el nuevo proyecto. Copie o cree subcarpetas en el disco según sea necesario.
- Copie también las vistas (por ejemplo, MainPage.xaml y MainPage.xaml.cs) en el nuevo nodo de proyecto. De nuevo, cree nuevas subcarpetas según sea necesario y quite las vistas existentes del proyecto. Sin embargo, antes de sobrescribir o quitar una vista generada por Visual Studio, mantenga una copia porque puede resultar útil hacer referencia a ella más adelante. La primera fase de migración de una aplicación Windows Phone Silverlight se centra en conseguir que se vea bien y funcione bien en una familia de dispositivos. Más adelante, llamará la atención para asegurarse de que las vistas se adapten bien a todos los factores de forma y, opcionalmente, a agregar cualquier código adaptable para sacar el máximo partido de una familia de dispositivos determinada.
- En el Explorador de soluciones, asegúrate de que Mostrar todos los archivos esté activado. Seleccione los archivos que copió, haga clic con el botón derecho en ellos y haga clic en Incluir en el proyecto. Esto incluirá automáticamente sus carpetas contenedora. Después, puede desactivar Mostrar todos los archivos si lo desea. Si lo prefiere, un flujo de trabajo alternativo es usar el comando Agregar elemento existente, después de crear las subcarpetas necesarias en el Explorador de soluciones de Visual Studio. Compruebe que los recursos visuales tienen la acción de compilación establecida en Contenido y Copiar en directorio de salida establecido en No copiar.
- Las diferencias en el espacio de nombres y los nombres de clase generarán muchos errores de compilación en esta fase. Por ejemplo, si abre las vistas generadas por Visual Studio, verá que son de tipo Page y no PhoneApplicationPage. Hay muchas diferencias de código imperativa y marcado XAML que en los temas siguientes de esta guía de portabilidad se tratan con detalle. Sin embargo, realizará un progreso rápido siguiendo estos pasos generales: cambie "clr-namespace" a "using" en las declaraciones de prefijo del espacio de nombres en el marcado XAML; use el tema Namespace y las asignaciones de clases y el comando Buscar y reemplazar de Visual Studio para realizar cambios masivos en el código fuente (por ejemplo, reemplace "System.Windows" por "Windows.UI.Xaml"); y en el editor de código imperativo de Visual Studio, use los comandos Resolver y organizar usings en el menú contextual para obtener cambios más específicos.
SDK de extensiones
La mayoría de las API de Plataforma universal de Windows (UWP) a las que llamará la aplicación porte se implementarán en el conjunto de API conocidas como la familia de dispositivos universales. Pero algunos se implementan en los SDK de extensión y Visual Studio solo reconoce las API que implementa la familia de dispositivos de destino de la aplicación o los SDK de extensión a los que se hace referencia.
Si recibe errores de compilación sobre los espacios de nombres o tipos o miembros que no se han encontrado, es probable que esto sea la causa. Abra el tema de la API en la documentación de referencia de API y vaya a la sección Requisitos: que le indicará cuál es la familia de dispositivos que implementa. Si no es la familia de dispositivos de destino, para que la API esté disponible para el proyecto, necesitará una referencia al SDK de extensión para esa familia de dispositivos.
Haga clic en Project Add Reference Windows Universal Extensions (Agregar referencia>>a extensiones universales> de Windows) y seleccione el SDK de extensión adecuado. Por ejemplo, si las API que quieres llamar solo están disponibles en la familia de dispositivos móviles y se introdujeron en la versión 10.0.x.y, a continuación, selecciona Extensiones de Windows Mobile para UWP.
Esto agregará la siguiente referencia al archivo del proyecto:
<ItemGroup>
<SDKReference Include="WindowsMobile, Version=10.0.x.y">
<Name>Windows Mobile Extensions for the UWP</Name>
</SDKReference>
</ItemGroup>
El nombre y el número de versión coinciden con las carpetas de la ubicación instalada del SDK. Por ejemplo, la información anterior coincide con este nombre de carpeta:
\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsMobile\10.0.x.y
A menos que la aplicación tenga como destino la familia de dispositivos que implementa la API, deberá usar la clase ApiInformation para probar la presencia de la API antes de llamarla (esto se denomina código adaptable). Esta condición se evaluará siempre que se ejecute la aplicación, pero solo se evaluará como true en los dispositivos en los que la API está presente y, por tanto, estará disponible para llamar. Use solo los SDK de extensión y el código adaptable después de comprobar primero si existe una API universal. Algunos ejemplos se proporcionan en la sección siguiente.
Consulte también Manifiesto del paquete de aplicación.
Maximizar el marcado y la reutilización de código
Encontrará que refactorizar un poco o agregar código adaptable (que se explica a continuación), le permitirá maximizar el marcado y el código que funciona en todas las familias de dispositivos. Estos son más detalles.
- Los archivos que son comunes a todas las familias de dispositivos no necesitan consideración especial. La aplicación usará esos archivos en todas las familias de dispositivos en las que se ejecuta. Esto incluye archivos de marcado XAML, archivos de código fuente imperativos y archivos de recursos.
- Es posible que la aplicación detecte la familia de dispositivos en la que se ejecuta y navegue a una vista diseñada específicamente para esa familia de dispositivos. Para obtener más información, consulta Detección de la plataforma en la que se ejecuta la aplicación.
- Una técnica similar que puede resultar útil si no hay ninguna alternativa es proporcionar un archivo de marcado o un archivo ResourceDictionary (o la carpeta que contiene el archivo) un nombre especial de modo que se cargue automáticamente en tiempo de ejecución solo cuando la aplicación se ejecute en una familia de dispositivos determinada. Esta técnica se ilustra en el caso práctico bookstore1 .
- Para usar características que no están disponibles en todas las familias de dispositivos (por ejemplo, impresoras, escáneres o el botón de cámara), puede escribir código adaptable. Consulte el tercer ejemplo de compilación condicional y código adaptable en este tema.
- Si quieres admitir tanto Windows Phone Silverlight como Windows 10, es posible que puedas compartir archivos de código fuente entre proyectos. Así es como: en Visual Studio, haga clic con el botón derecho en el proyecto en Explorador de soluciones, seleccione Agregar elemento existente, seleccione los archivos que se van a compartir y, a continuación, haga clic en Agregar como vínculo. Almacene los archivos de código fuente en una carpeta común en el sistema de archivos donde los proyectos que se vinculan a ellos puedan verlos y no olvide agregarlos al control de código fuente. Si puede factorizar el código fuente imperativo para que la mayoría, si no todo, de un archivo funcione en ambas plataformas, no es necesario tener dos copias de él. Puede encapsular cualquier lógica específica de la plataforma en el archivo dentro de directivas de compilación condicional siempre que sea posible o en condiciones en tiempo de ejecución cuando sea necesario. Consulte la sección siguiente y Directivas de preprocesador de C#.
- Para reutilizar en el nivel binario, en lugar del nivel de código fuente, hay bibliotecas de clases portables que admiten el subconjunto de API de .NET que están disponibles en Windows Phone Silverlight, así como el subconjunto de aplicaciones de Windows 10 (.NET Core). Los ensamblados de la biblioteca de clases portables son compatibles con estas plataformas .NET y mucho más. Use Visual Studio para crear un proyecto destinado a una biblioteca de clases portable. Consulte Desarrollo multiplataforma con la biblioteca de clases portable.
Compilación condicional y código adaptable
Si quieres admitir tanto Windows Phone Silverlight como Windows 10 en un solo archivo de código, puedes hacerlo. Si examinas el proyecto de Windows 10 en las páginas de propiedades del proyecto, verás que el proyecto define WINDOWS_UAP como un símbolo de compilación condicional. En general, puede usar la siguiente lógica para realizar la compilación condicional.
#if WINDOWS_UAP
// Code that you want to compile into the Windows 10/11 app.
#else
// Code that you want to compile into the Windows Phone Silverlight app.
#endif // WINDOWS_UAP
Si tienes código que has estado compartiendo entre una aplicación de Windows Phone Silverlight y una aplicación de Windows Runtime 8.x, es posible que ya tengas código fuente con lógica como esta:
#if NETFX_CORE
// Code that you want to compile into the Windows Runtime 8.x app.
#else
// Code that you want to compile into the Windows Phone Silverlight app.
#endif // NETFX_CORE
Si es así, y si ahora quieres admitir Windows 10 además, también puedes hacerlo.
#if WINDOWS_UAP
// Code that you want to compile into the Windows 10/11 app.
#else
#if NETFX_CORE
// Code that you want to compile into the Windows Runtime 8.x app.
#else
// Code that you want to compile into the Windows Phone Silverlight app.
#endif // NETFX_CORE
#endif // WINDOWS_UAP
Es posible que haya usado la compilación condicional para limitar el control del botón Atrás del hardware a Windows Phone. En Windows 10, el evento de botón Atrás es un concepto universal. Los botones Atrás implementados en hardware o en software generarán todo el evento BackRequested , por lo que es el que se va a controlar.
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested +=
this.ViewModelLocator_BackRequested;
...
private void ViewModelLocator_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
// Handle the event.
}
Es posible que haya usado la compilación condicional para limitar el control del botón de cámara de hardware a Windows Phone. En Windows 10, el botón de cámara de hardware es un concepto particular de la familia de dispositivos móviles. Dado que un paquete de aplicación se ejecutará en todos los dispositivos, cambiamos nuestra condición en tiempo de compilación a una condición en tiempo de ejecución mediante lo que se conoce como código adaptable. Para ello, usamos la clase ApiInformation para consultar en tiempo de ejecución la presencia de la clase HardwareButtons. HardwareButtons se define en el SDK de extensión móvil, por lo que es necesario agregar una referencia a ese SDK a nuestro proyecto para que este código se compile. Sin embargo, tenga en cuenta que el controlador solo se ejecutará en un dispositivo que implemente los tipos definidos en el SDK de extensión móvil y que sea la familia de dispositivos móviles. Por lo tanto, el código siguiente solo tiene cuidado de usar características que están presentes, aunque lo logra de una manera diferente de la compilación condicional.
// Note: Cache the value instead of querying it more than once.
bool isHardwareButtonsAPIPresent = Windows.Foundation.Metadata.ApiInformation.IsTypePresent
("Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
Windows.Phone.UI.Input.HardwareButtons.CameraPressed +=
this.HardwareButtons_CameraPressed;
}
...
private void HardwareButtons_CameraPressed(object sender, Windows.Phone.UI.Input.CameraEventArgs e)
{
// Handle the event.
}
Consulta también Detección de la plataforma en la que se ejecuta la aplicación.
Manifiesto del paquete de aplicación
La configuración del proyecto (incluidas las referencias de SDK de extensión) determina el área expuesta de LA API a la que puede llamar la aplicación. Pero el manifiesto del paquete de la aplicación es lo que determina el conjunto real de dispositivos en los que los clientes pueden instalar la aplicación desde la Tienda. Para obtener más información, consulta Ejemplos en TargetDeviceFamily.
Vale la pena saber cómo editar el manifiesto del paquete de la aplicación, ya que los temas que siguen hablan sobre cómo usarlo para varias declaraciones, funcionalidades y otras configuraciones que necesitan algunas características. Puede usar el editor de manifiestos del paquete de la aplicación de Visual Studio para editarlo. Si no se muestra el Explorador de soluciones, selecciónelo en el menú Ver. Haga doble clic en Package.appxmanifest. Se abrirá la ventana del editor de manifiestos. Seleccione la pestaña adecuada para realizar cambios y, a continuación, guarde los cambios. Es posible que quieras asegurarte de que el elemento pm:PhoneIdentity del manifiesto de la aplicación porte coincide con lo que se encuentra en el manifiesto de la aplicación de la aplicación que vas a migrar (para obtener detalles completos, consulta el tema pm:PhoneIdentity).
Consulta Referencia del esquema del manifiesto del paquete para Windows 10.
El siguiente tema es Solución de problemas.