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 WinUI 3.
Resumen de las API y/o diferencias en las 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 controlador de la ventana (HWND) en MessageDialog y en Pickers.
Para usar las API de DataTransferManager, debe asociarlas a la ventana.
Para ContentDialog y Popup, debe establecer su propiedad XamlRoot.
Es posible que tenga que refactorizar el marcado XAML de Administrador de estado visual y Page.Resources.
En el SDK de Aplicaciones para Windows, AcrylicBrush siempre toma muestra del contenido de la aplicación.
Cambiar Windows.UI.Xaml.Window.Current a App.Window
Esta sección se aplica si utiliza la propiedad Windows.UI.Xaml.Window.Current en su 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 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 idea de una ventana actual o principal utilizando 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 clases App, cambie Window.Current
a App.Window
, de la siguiente manera:
// 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 Pickers
En su aplicación para UWP, si usa 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 un FolderPicker).
Los pasos que debe seguir en una aplicación de escritorio se describen en Visualización de objetos de la 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, consulte la sección ContentDialog y Popup a continuación.
Este es un código de UWP típico 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 su aplicación para UWP, si llama 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 uso compartido a 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 su aplicación para UWP está usando 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 de UWP típico 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 tiene 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 tenga solo 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 necesite 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 las funcionalidades como Resources y DataContext no existen en él. Tampoco ninguno de los eventos, como Load y Unload. Para obtener más información y soluciones alternativas, consulte Administrador de estado visual y Page.Resources.
Si, por otro lado, desea o necesita navegar entre las páginas de su aplicación de SDK de Aplicaciones para Windows, puede hacerlo migrando los métodos App.OnLaunched y App::OnNavigationFailed desde su aplicación para UWP. En App.OnLaunched, busque el código de navegación (el código que crea rootFrame y vaya a la primera página de la aplicación) y combínelo justo entre las dos líneas de código existentes (las líneas que crean una ventana y después la activan). También deberá migrar el código que ha copiado y pegado. Para obtener un ejemplo de código sencillo, consulte Clase Page.
Administrador de estado visual y Page.Resources
Consulte también ¿Necesito implementar la navegación de páginas? Si tiene una aplicación para UWP lo suficientemente sencilla como para copiar el marcado XAML y el código subyacente en MainWindow, tenga 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 del Administrador de estado visual (consulte Tutorial: Crear diseños adaptables). Sin embargo, tienes estas dos opciones:
- Agregar un elemento UserControl al proyecto y migrar el marcado y el código subyacente a él. A continuación, colocar una instancia de ese control de usuario en MainWindow.
- Agregar un elemento Page al proyecto y migrar el marcado y el código subyacente a él. A continuación, agregar código a la clase App para ir a esa página al inicio, como se describe en ¿Necesito implementar la navegación de páginas?
Además, no podrá copiar un elemento <Page.Resources>
a MainWindow y simplemente cambiarle el nombre a <Window.Resources>
. En su lugar, coloque el elemento Resources debajo del contenedor de diseño raíz (por ejemplo, Grid) en el marcado XAML para MainWindow. Eso 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 el SDK de Aplicaciones para Windows. En el SDK de Aplicaciones para Windows, AcrylicBrush siempre toma muestra del contenido de la aplicación.
Por lo tanto, si accede a la propiedad AcrylicBrush.BackgroundSource en el código fuente de su aplicación para UWP (ya sea en el marcado XAML o en código imperativo), quite ese código al migrar la aplicación a la SDK de Aplicaciones para Windows. En su lugar, use la clase DesktopAcrylicController.