Migración de la interfaz de usuario (incluido WinUI 3)

En este tema se muestra cómo migrar el código de la interfaz de usuario (UI), incluida la migración a la Biblioteca de interfaz de usuario de Windows (WinUI) 3.

Resumen de las diferencias de api o características

La propiedad Window.Current se migra a App.Window. Y el método CoreDispatcher.RunAsync se migra a DispatcherQueue.TryEnqueue.

Debe establecer el identificador de la ventana (HWND) en un MessageDialog y en selectores.

Para usar las API de DataTransferManager , debe asociarlas a la ventana.

Para ContentDialog y Popup, debes establecer su propiedad XamlRoot .

Es posible que tengas que refactorizar el marcado XAML De Visual State Manager y Page.Resources .

En el SDK de Aplicaciones para Windows, AcrylicBrush siempre muestra el contenido de la aplicación.

Cambie Windows.UI.Xaml.Window.Current a App.Window

Esta sección se aplica si usas la propiedad Windows.UI.Xaml.Window.Current en tu aplicación para UWP. Esa propiedad no se admite en el SDK de Aplicaciones para Windows, por lo que en esta sección se describe cómo portar el código de UWP que usa Window.Current.

// MainPage.xaml.cs in a UWP app
var width = Window.Current.Bounds.Width;
// MainPage.xaml.cpp in a UWP app
auto width{ Window::Current().Bounds().Width };

La aplicación SDK de Aplicaciones para Windows puede agregar su propia noción de una ventana actual o principal mediante una propiedad estática pública en la clase App.

// App.xaml.cs in a Windows App SDK app
public partial class App : Application
{
    ...
    public static Window Window { get { return m_window; } }
    private static Window m_window;
}
// App.xaml.h in a Windows App SDK app
...
struct App : AppT<App>
{
    ...
    static winrt::Microsoft::UI::Xaml::Window Window(){ return window; };

private:
    static winrt::Microsoft::UI::Xaml::Window window;
};
...

// App.xaml.cpp
...
winrt::Microsoft::UI::Xaml::Window App::window{ nullptr };
...

A continuación, dentro de la propia clase App , puede cambiar Window.Current a simplemente window. Fuera de la clase App , cambie Window.Current a App.Window, como se indica a continuación:

// MainPage.xaml.cs in a UWP app
var width = App.Window.Bounds.Width;
// MainPage.xaml.cpp in a UWP app
#include <App.xaml.h>
auto width{ App::Window().Bounds().Width };

MessageDialog y selectores

En tu aplicación para UWP, si usas determinados tipos de los espacios de nombres Windows.UI.Popups o Windows.Storage.Pickers , esta sección contiene información para ayudarte a migrar ese código. Los ejemplos de código siguientes usan MessageDialog, pero puede aplicar exactamente las mismas técnicas para mostrar un selector (por ejemplo, un FileOpenPicker, un FileSavePicker o folderPicker).

Los pasos que debe seguir en una aplicación de escritorio se describen en Mostrar objetos de interfaz de usuario de WinRT que dependen de CoreWindow.

Nota

Para las nuevas aplicaciones, se recomienda usar el control ContentDialog en lugar de MessageDialog. Para obtener más información, consulta la sección ContentDialog y Popup a continuación.

Este es un código típico de UWP para mostrar un messageDialog.

// In a UWP app
var showDialog = new Windows.UI.Popups.MessageDialog("Message here");
await showDialog.ShowAsync();
// In a UWP app
auto showDialog{ Windows::UI::Popups::MessageDialog(L"Message here") };
co_await showDialog.ShowAsync();

Y este es el código equivalente en una aplicación de SDK de Aplicaciones para Windows.

// MainWindow.xaml.cs in a WinUI 3 app
var showDialog = new Windows.UI.Popups.MessageDialog("Message here");
WinRT.Interop.InitializeWithWindow.Initialize(showDialog,
    WinRT.Interop.WindowNative.GetWindowHandle(this));
await showDialog.ShowAsync();
// pch.h in a WinUI 3 app
...
#include <Shobjidl.h>
#include <microsoft.ui.xaml.window.h>
#include <winrt/Windows.UI.Popups.h>
...

// MainWindow.xaml.cpp
...
auto showDialog{ Windows::UI::Popups::MessageDialog(L"Message here") };

auto windowNative{ this->m_inner.as<::IWindowNative>() };
HWND hWnd{ 0 };
windowNative->get_WindowHandle(&hWnd);
showDialog.as<::IInitializeWithWindow>()->Initialize(hWnd);

co_await showDialog.ShowAsync();

DataTransferManager

En tu aplicación para UWP, si llamas al método DataTransferManager.ShowShareUI , esta sección contiene información para ayudarte a migrar ese código.

Este es un código de UWP típico que llama a ShowShareUI.

// In a UWP app
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();

dataTransferManager.DataRequested += (sender, args) =>
{
    args.Request.Data.Properties.Title = "In a UWP app...";
    args.Request.Data.SetText("...display the user interface for sharing content with another app.");
    args.Request.Data.RequestedOperation =
        Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
};

Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI();
// In a UWP app
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
...
auto dataTransferManager{ Windows::ApplicationModel::DataTransfer::DataTransferManager::GetForCurrentView() };

dataTransferManager.DataRequested([](Windows::ApplicationModel::DataTransfer::DataTransferManager const& /* sender */,
    Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs const& args)
    {
        args.Request().Data().Properties().Title(L"In a UWP app...");
        args.Request().Data().SetText(L"...display the user interface for sharing content with another app.");
        args.Request().Data().RequestedOperation(Windows::ApplicationModel::DataTransfer::DataPackageOperation::Copy);
    });

Windows::ApplicationModel::DataTransfer::DataTransferManager::ShowShareUI();

Para usar DataTransferManager.ShowShareUI en la aplicación de SDK de Aplicaciones para Windows, debe asociar la interfaz de usuario de Compartir con la ventana. Y eso debe realizarse manualmente. Para obtener más información y ejemplos de código, consulta Mostrar objetos de interfaz de usuario de WinRT que dependen de CoreWindow.

ContentDialog y Popup

Si en tu aplicación para UWP usas las clases Windows.UI.Xaml.Controls.ContentDialog o Windows.UI.Xaml.Controls.Primitives.Popup , esta sección contiene información para ayudarte a migrar ese código. Los ejemplos de código siguientes usan ContentDialog, pero puede aplicar exactamente las mismas técnicas para mostrar un objeto Popup .

Este es un código típico de UWP para mostrar un contentDialog.

// MainPage.xaml.cs in a UWP app
var unsupportedFilesDialog = new ContentDialog();
// Set Title, Content, etc.
await unsupportedFilesDialog.ShowAsync();
// MainPage.xaml.cpp in a UWP app
ContentDialog unsupportedFilesDialog{};
// Set Title, Content, etc.
co_await unsupportedFilesDialog.ShowAsync();

En la aplicación SDK de Aplicaciones para Windows, solo tienes que establecer también la propiedad XamlRoot del cuadro de diálogo. Esta es la manera de hacerlo.

// MainPage.xaml.cs in a Windows App SDK app
var unsupportedFilesDialog = new ContentDialog();
// Set Title, Content, etc.
unsupportedFilesDialog.XamlRoot = this.Content.XamlRoot;
await unsupportedFilesDialog.ShowAsync();
// MainPage.xaml.cpp in a Windows App SDK app
ContentDialog unsupportedFilesDialog{};
// Set Title, Content, etc.
unsupportedFilesDialog.XamlRoot(this->Content().XamlRoot());
co_await unsupportedFilesDialog.ShowAsync();

¿Es necesario implementar la navegación de páginas?

En un proyecto de UWP, de forma predeterminada habrá código de navegación en los métodos de la clase App , incluso si la aplicación es lo suficientemente simple como para que solo tenga una página.

Al crear un nuevo proyecto de SDK de Aplicaciones para Windows en Visual Studio, la plantilla de proyecto proporciona una clase MainWindow (de tipo Microsoft.UI.Xaml.Window), pero no page. Y la plantilla de proyecto no proporciona ningún código de navegación.

Para una aplicación de SDK de Aplicaciones para Windows que sea lo suficientemente sencilla (una aplicación de página única), es posible que pueda simplificarla. Es posible que no necesites crear páginas ni controles de usuario en el proyecto de SDK de Aplicaciones para Windows, sino copiar el marcado XAML y el código subyacente de esa sola página en MainWindow. Sin embargo, hay algunas cosas que MainWindow no admite. Window no es dependencyObject, por lo que no existen funcionalidades como Resources y DataContext . Ninguno de los eventos, como Load y Unload. Para obtener más información y soluciones alternativas, consulta Visual State Manager y Page.Resources.

Si, por otro lado, quieres o necesitas navegación entre las páginas de tu aplicación de SDK de Aplicaciones para Windows, puedes hacerlo mediante la migración de los métodos App.OnLaunched y App::OnNavigationFailed desde tu aplicación para UWP. En App.OnLaunched, busque el código de navegación (el código que crea rootFrame y navegue a la primera página de la aplicación) y combítelo directamente entre las dos líneas de código existentes (las líneas que crean una ventana y, a continuación, la activan). También deberá migrar el código que ha pegado. Para obtener un ejemplo de código sencillo, vea Clase Page.

Visual State Manager y Page.Resources

Consulte también ¿Necesito implementar la navegación de páginas?. Si tienes una aplicación para UWP lo suficientemente sencilla como para copiar el marcado XAML y el código subyacente en MainWindow, ten en cuenta estas excepciones.

La clase MainWindow (de tipo Microsoft.UI.Xaml.Window) no es un control, por lo que no es compatible con el marcado XAML y el código subyacente de Visual State Manager (consulte Tutorial: Creación de diseños adaptables). Sin embargo, tiene estas dos opciones:

  • Agregue un elemento UserControl al proyecto y migre el marcado y el código subyacente a ese. A continuación, coloque una instancia de ese control de usuario en MainWindow.
  • Agregue un elemento Page al proyecto y migre el marcado y el código subyacente a ese. A continuación, agregue código a la clase App para ir a esa página en el inicio, como se describe en ¿Necesito implementar la navegación de páginas?.

Además, no podrá copiar un <Page.Resources> elemento en MainWindow y simplemente cambiar su nombre a <Window.Resources>. En su lugar, el elemento Resources primario del contenedor de diseño raíz (por ejemplo, una cuadrícula) en el marcado XAML para MainWindow. Esto tendrá el siguiente aspecto:

<Window ...>
    <Grid>
        <Grid.Resources>...</Grid.Resources>
        ...
    </Grid>
</Window>

Propiedad AcrylicBrush.BackgroundSource

La propiedad AcrylicBrush.BackgroundSource existe en UWP, pero no en la SDK de Aplicaciones para Windows. En el SDK de Aplicaciones para Windows, AcrylicBrush siempre muestra el contenido de la aplicación.

Por lo tanto, si estás accediendo a la propiedad AcrylicBrush.BackgroundSource en el código fuente de tu aplicación para UWP (ya sea en el marcado XAML o en código imperativo), quita ese código al migrar la aplicación a la SDK de Aplicaciones para Windows. En su lugar, use la clase DesktopAcrylicController .