Migración de un proyecto de Windows Runtime 8.x a un proyecto de UWP
Tiene dos opciones al comenzar el proceso de portabilidad. Una consiste en editar una copia de los archivos de proyecto existentes, incluido el manifiesto del paquete de aplicación (para esa opción, consulta la información sobre cómo actualizar los archivos de proyecto en Migrar aplicaciones a la Plataforma universal de Windows (UWP)). La otra opción es crear un nuevo proyecto de Windows 10 en Visual Studio y copiar los archivos en él. En la primera sección de este tema se describe esa segunda opción, pero el resto del tema tiene información adicional aplicable a ambas opciones. También puedes elegir mantener el nuevo proyecto de Windows 10 en la misma solución que los proyectos existentes y compartir archivos de código fuente mediante un proyecto compartido. O bien, puede mantener el nuevo proyecto en una solución propia y compartir archivos de código fuente mediante la característica de archivos vinculados en Visual Studio.
Crear el proyecto y copiar archivos en él
Estos pasos se centran en la opción de crear un nuevo proyecto de Windows 10 en Visual Studio y copiar los archivos en él. Algunos de los detalles relacionados con el número de proyectos que cree y los archivos que copie dependerán de los factores y decisiones descritos en Si tiene una aplicación Universal 8.1 y las secciones siguientes. En estos pasos se da por supuesto el caso más sencillo.
- 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 Universal 8.1, 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 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 Universal 8.1 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.
- Es probable que vea algunos errores de compilación en esta fase. Pero, si sabe lo que necesita cambiar, puede usar el comando Buscar y reemplazar de Visual Studio para realizar cambios masivos en el código fuente y, en el editor de código imperativo de Visual Studio, use los comandos Resolver y organizar usos en el menú contextual para realizar cambios más específicos.
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 .
- Deberías poder quitar muchas de las directivas de compilación condicional en el código fuente de la aplicación Universal 8.1 si solo necesitas admitir Windows 10. Consulte Compilación condicional y código adaptable en este tema.
- 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 Windows 8.1, Windows Phone 8.1 y Windows 10, puedes mantener tres proyectos en la misma solución y compartir código con un proyecto compartido. Como alternativa, puede 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 pueden verlos. Y no olvide agregarlos al control de código fuente.
- Para reutilizarlo en el nivel binario, en lugar del nivel de código fuente, consulte Creación de componentes de Windows Runtime en C# y Visual Basic. También hay bibliotecas de clases portables, que admiten el subconjunto de API de .NET que están disponibles en .NET Framework para Windows 8.1, Windows Phone 8.1 y aplicaciones de Windows 10 (.NET Core) y .NET Framework completa. Los ensamblados de la biblioteca de clases portables son compatibles con todas estas plataformas. Use Visual Studio para crear un proyecto destinado a una biblioteca de clases portable. Consulte Desarrollo multiplataforma con la biblioteca de clases portable.
SDK de extensiones
La mayoría de las API de Windows Runtime que la aplicación Universal 8.1 ya llama se implementan en el conjunto de API conocidas como 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.
Compilación condicional y código adaptable
Si usas la compilación condicional (con directivas de preprocesador de C#) para que los archivos de código funcionen tanto en Windows 8.1 como en Windows Phone 8.1, ahora puedes revisar esa compilación condicional a la luz del trabajo de convergencia realizado en Windows 10. Convergencia significa que, en la aplicación de Windows 10, algunas condiciones se pueden quitar por completo. Otros cambian a comprobaciones en tiempo de ejecución, como se muestra en los ejemplos siguientes.
Nota Si quieres admitir Windows 8.1, Windows Phone 8.1 y Windows 10 en un solo archivo de código, también 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. Por lo tanto, puede usarlo en combinación con WINDOWS_APP y WINDOWS_PHONE_APP. Estos ejemplos muestran el caso más sencillo de quitar la compilación condicional de una aplicación Universal 8.1 y sustituir el código equivalente para una aplicación de Windows 10.
En este primer ejemplo se muestra el patrón de uso de la API PickSingleFileAsync (que solo se aplica a Windows 8.1) y la API PickSingleFileAndContinue (que solo se aplica a Windows Phone 8.1).
#if WINDOWS_APP
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAsync
#else
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAndContinue
#endif // WINDOWS_APP
Windows 10 converge en la API PickSingleFileAsync , por lo que el código simplifica esto:
// Use Windows.Storage.Pickers.FileOpenPicker.PickSingleFileAsync
En este ejemplo, se controla el botón Atrás de hardware, pero solo en Windows Phone.
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.BackPressed += this.HardwareButtons_BackPressed;
#endif // WINDOWS_PHONE_APP
...
#if WINDOWS_PHONE_APP
void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
// Handle the event.
}
#endif // WINDOWS_PHONE_APP
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.
}
Este ejemplo final es similar al anterior. Aquí se controla el botón de cámara de hardware, pero de nuevo, solo en el código compilado en el paquete de la aplicación Windows Phone.
#if WINDOWS_PHONE_APP
Windows.Phone.UI.Input.HardwareButtons.CameraPressed += this.HardwareButtons_CameraPressed;
#endif // WINDOWS_PHONE_APP
...
#if WINDOWS_PHONE_APP
void HardwareButtons_CameraPressed(object sender, Windows.Phone.UI.Input.CameraEventArgs e)
{
// Handle the event.
}
#endif // WINDOWS_PHONE_APP
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, este código es moralmente equivalente al código universal 8.1 en que solo tiene cuidado de usar características que están presentes, aunque logra eso de una manera diferente.
// 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 la aplicación
En el tema What's changed in Windows 10 (Novedades de Windows 10 ) se enumeran los cambios en la referencia del esquema del manifiesto de paquete para Windows 10, incluidos los elementos que se han agregado, quitado y cambiado. Para obtener información de referencia sobre todos los elementos, atributos y tipos del esquema, vea Jerarquía de elementos. Si vas a migrar una aplicación de Windows Phone Store, o si la aplicación es una actualización de una aplicación desde la Tienda Windows Phone, asegúrate de que el elemento mp:PhoneIdentity coincida con lo que hay en el manifiesto de la aplicación de la aplicación anterior (usa los mismos GUID asignados a la aplicación por la Tienda). Esto garantizará que los usuarios de la aplicación que actualicen a Windows 10 o Windows 11 recibirán la nueva aplicación como una actualización, no un duplicado. Consulte el tema de referencia mp:PhoneIdentity para obtener más detalles.
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.
Puedes editar el manifiesto del paquete de aplicación para establecer varias declaraciones, funcionalidades y otras configuraciones que necesiten 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.
El siguiente tema es Solución de problemas.